自己写一个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. mysql 数据表操作 目录

    mysql 数据表操作 存储引擎介绍 mysql 使用存储引擎 mysql 数据表的增删改查 mysql 数据类型 mysql 约束条件

  2. 下载pywinauto

    1.下载pywinauto 链接:http://pywinauto.github.io/ 2.将安装包放到D:python36\script,进入pywinauto目录,按shift+右键,进入命令窗 ...

  3. 利用 PorterDuff 动态改变资源色值,缩减安装包大小

    利用 PorterDuff 改变资源原有色值,从而实现只需要一个资源文件,就可以表示几种不同的状态,如在线或者离线等等 public Drawable colorDrawable(Resources ...

  4. nginx的访问控制

    一.基于Basic Auth认证与基于IP的访问控制 一.基于Basic Auth认证 Nginx提供HTTP的Basic Auth功能,配置了Basic Auth之后,需要输入正确的用户名和密码之后 ...

  5. cocos JS for循环让精灵从屏幕中间往两边排列散开

    //this.ShowImg[i] 需要排列什么就push加进数组里面,一个for循环计算即可 var size = this.ShowImg.length;var count = size; for ...

  6. Python对list列表及子列表进行排序

    python代码,对list进行升序排序,所有子列表也要进行排序 def iterList(listVar): listVar = sorted(listVar) for i,v in enumera ...

  7. SQLServer 里面的 DDL,DML,DCL,TCL(转)

    1.DDL (Data Definition Language )数据库定义语言 statements are used to define the database structure or sch ...

  8. Thinkphp 3.2 验证码图片显示错误解决方法

    在调用验证码之前加上 ob_clean(); 不显示验证码的代码: public function verify(){ $verify = new \Think\Verify(); $verify-& ...

  9. Hibernate框架的第四天

    ## Hibernate框架的第四天 ## ---------- **回顾:Hibernate框架的第三天** 1. 一对多关联关系映射 * JavaBean的编写 * 编写映射的配置文件 * 使用级 ...

  10. POJ 2155 Matrix(二维BIT)

    Matrix [题目链接]Matrix [题目类型]二维BIT &题解: bit只能单点更新,恰好,这题可以想一下就可以用单点更新解决了. 只不过最后我交上去居然T了,想了10多分钟,试了一下 ...