自己写一个websocket

原理更多参考--   https://www.cnblogs.com/zunzunQ/p/8549180.html
原理简介:
client端 握手请求中 包含一个base64 encode的随机字符串,
server端 magic_string+str sha1摘要之后base64加密, 发给client
服务器完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦 (回调机制)
import socket, hashlib, base64

sock = socket.socket()
sock.bind(('127.0.0.1', 9000))
sock.listen(5)
'''
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:9000\r\n
Connection: Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36\r\n
Upgrade: websocket\r\n --建立--
Origin: http://localhost:63342\r\n
Sec-WebSocket-Version: 13\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Sec-WebSocket-Key: vNtQ8bVSNRPL5p+xo1X5CA==\r\n 验证 一按钥匙
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n
'''
'''
b'GET / HTTP/1.1\r\n -- 单纯http地址栏访问
Host: 127.0.0.1:9000\r\n
Connection: keep-alive\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n\r\n'
'''
conn, addr = sock.accept()
data = conn.recv(1024)
# print(data) def get_header(data): # 获取头部信息
header_dict = {}
header_str = data.decode('utf8')
for i in header_str.split('\r\n'):
if str(i).startswith('Sec-WebSocket-Key'):
header_dict['Sec-WebSocket-Key'] = i.split(':')[1].strip()
return header_dict headers = get_header(data)
magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' # magic_string = 魔法字符串
value = headers['Sec-WebSocket-Key'] + magic_string
print(value) #mzrsVOiYogmzB8fYcyMBpw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest()) # 固定加密算法
print(ac) #b'0Cu1dAA7U6tFsJS4EVkIDLcvKDU='
response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade:websocket\r\n" \
"Connection: Upgrade\r\n" \
"Sec-WebSocket-Accept: %s\r\n" \
"WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n"
response_str = response_tpl % (ac.decode('utf-8'))
conn.send(response_str.encode('utf8')) # 响应握手信息 while True:
msg = conn.recv(8096)
print(msg)

解密过程  分析

hashstr = b'\x81\x89\xbc\xb8,\xb5Y6\xa5P\x12\x0b\xc8\x0f:'
# b'\x81 \x83 \xceH\xb6\x85\xffz\x85' # 将第二个字节也就是 \x83 第9-16位 进行与127进行 与位 运算
payload = hashstr[1] & 127
print(payload)
if payload == 127:
extend_payload_len = hashstr[2:10] # 顾头不顾尾
mask = hashstr[10:14]
decoded = hashstr[14:]
# 当位运算结果等于127时,则第3-10个字节为数据长度
# 第11-14字节为mask 解密所需字符串
# 则数据为第15字节至结尾 if payload == 126:
extend_payload_len = hashstr[2:4]
mask = hashstr[4:8]
decoded = hashstr[8:]
# 当位运算结果等于126时,则第3-4个字节为数据长度 255*255+510=65535 21845汉字
# 第5-8字节为mask 解密所需字符串
# 则数据为第9字节至结尾 if payload <= 125:
extend_payload_len = None
mask = hashstr[2:6]
decoded = hashstr[6:] # 当位运算结果小于等于125时,则这个数字就是数据的长度
# 第3-6字节为mask 解密所需字符串
# 则数据为第7字节至结尾 str_byte = bytearray() # 字节流 for i in range(len(decoded)):
byte = decoded[i] ^ mask[i % 4] # 异或运算 上下为0就是0 上下有1就是1
str_byte.append(byte) print(str_byte.decode("utf8")) # 主要解决中文 厉害了 # # 1字节 = 8 bit 与位运算
#
# 11111111 最大255
# 2/4/8/16/32/64/138/256

加密过程 -- 分析

import struct
msg_bytes = "hello".encode("utf8") #转bytes
token = b"\x81" # 数据标准格式
length = len(msg_bytes) #第二位就是数据长度 if length < 126:
token += struct.pack("B", length)
elif length == 126:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length) msg = token + msg_bytes print(msg)

总结

WebSocket的工作原理
.握手
客户端 Sec-WebSocket-Key
响应 base64(sha1(Sec-WebSocket-Key + magic_string)) .解密:
与127 进行"与"位运算 结果是两个数的最小值
. == 第3-10个字节表示该数据的长度
. == 第3-4个字节表示该数据的长度
. <= 当前这个数字就是Websocket发送的数据长度

websocket 原理的更多相关文章

  1. WebSocket原理

    一 . WebSocket原理 1.1.背景 WebSocket 是基于Http 协议的改进,Http 为无状态协议,基于短连接,需要频繁的发起请求,第二 Http 只能客户端发起请求,服务端无法主动 ...

  2. python全栈开发day115、116-websocket、websocket原理、websocket加解密、简单问答机器人实现

    1.websocket 1.websocket 与轮询 轮询: 不断向服务器发起询问,服务器还不断的回复 浪费带宽,浪费前后端资源 保证数据的实时性 长轮询: 1.客户端向服务器发起消息,服务端轮询, ...

  3. WebSocket原理与实践(四)--生成数据帧

    WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...

  4. WebSocket原理与实践(三)--解析数据帧

    WebSocket原理与实践(三)--解析数据帧 1-1 理解数据帧的含义:   在WebSocket协议中,数据是通过帧序列来传输的.为了数据安全原因,客户端必须掩码(mask)它发送到服务器的所有 ...

  5. WebSocket原理与实践(二)---WebSocket协议

    WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...

  6. WebSocket原理与实践(一)---基本原理

    WebSocket原理与实践(一)---基本原理 一:为什么要使用WebSocket?1. 了解现有的HTTP的架构模式:Http是客户端/服务器模式中请求-响应所用的协议,在这种模式中,客户端(一般 ...

  7. python 全栈开发,Day139(websocket原理,flask之请求上下文)

    昨日内容回顾 flask和django对比 flask和django本质是一样的,都是web框架. 但是django自带了一些组件,flask虽然自带的组件比较少,但是它有很多的第三方插件. 那么在什 ...

  8. WebSocket原理说明

    WebSocket原理说明 众所周知,Web应用的通信过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现.这种机制对于信息变化不是特别频繁的应 ...

  9. Websocket - Websocket原理(握手、解密、加密)、基于Python实现简单示例

    一.Websocket原理(握手.解密.加密) WebSocket协议是基于TCP的一种新的协议.WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符.它实 ...

随机推荐

  1. 20190228 搭建Hadoop基础环境

    下载VMware 12 版本以上 下载CentOS 7以上版本 安装虚拟机,安装系统时,注意设置root 账号和密码 虚拟机配置网络,命令ip addr 查看IP 地址,(配置网络网上有很多办法,百度 ...

  2. Java基础知识(重载和覆盖)

    重载(overload): 在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了. 即当函数同名时,只看参数列表.和返回值类型没关系. 重 ...

  3. 报错解决——SSL: CERTIFICATE_VERIFY_FAILED

    SSL: CERTIFICATE_VERIFY_FAILED Python 升级到 2.7.9 之后引入了一个新特性,当使用urllib.urlopen打开一个 https 链接时,会验证一次 SSL ...

  4. shell进阶函数

    函数的定义和用途 函数function是由若干条shell命令组成的语句块,实现shell代码的重用和模块化编程. 函数和shell程序的异同点 它与shell程序形式上是相似的,不同的是它不是一个单 ...

  5. Python笔记:调用函数,带扩号和和不带括号的区别

    调用函数,如果带括号,那么是调用函数运行后的结果, 调用函数不带括号,调用的是函数本身 例如: def cun (a,b): return a+b print(cun) : 调用函数,打印的是函数 p ...

  6. [py]Python locals() 函数

    Python locals() 函数作用 http://www.runoob.com/python/python-func-locals.html locals() 函数会以字典类型返回当前位置的全部 ...

  7. 【Java】-NO.16.EBook.4.Java.1.012-【疯狂Java讲义第3版 李刚】- JDBC

    1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.012-[疯狂Java讲义第3版 李刚]-  JDBC Style:EBook Series:Java ...

  8. es6 数组..... ==和===的区别 es6的递归方式 es6find函数 timer setTimeout v-html的用法,-

    相当于push了  find函数来找到某个值 如果新建一个 setTimeout 的timer 首先得清除这个timer. v-html用法之一就是加载后台传过来的模板

  9. Maven中的-D(Properties属性)和-P(Profiles配置文件)

    -D代表(Properties属性) 使用命令行设置属性-D的正确方法是: mvn -DpropertyName=propertyValue clean package 如果propertyName不 ...

  10. ubuntu16.4菜单栏不见,终端不见解决方法

    1.ctrl+alt+f1进入命令行 2. sudo apt-get install gnome-terminal 3.sudo apt-get install unity 4.setsid unit ...