赞
踩
参考博文:https://www.cnblogs.com/wupeiqi/p/6558766.html
Http——socket实现,短链接。链接之后断开。只能请求响应。
WebSocket——socket实现,双工通道。想什么时候断就什么时候断。不仅请求响应,还能推送。
本质就是Socket创建链接,不断开。
知道了本质,就可以从socket入手:
服务端(socket服务端)
1、服务端开启socket,监听IP和端口
3、允许链接
*5、服务端接收到特殊值【特殊值加密,sha1加密,magic string=258EAFA5-E914-47DA-95CA-C5AB0DC85B11】(这个magic string 是固定值)
6、加密后的值发送给客户端
客户端(浏览器)
2、客户端发起请求(IP和端口)
*4、客户端生成一个特殊值,向服务端发送一段特殊值 “xxxxxxxxx”。切客户端自己加密这段特殊值,但不发送。
7、客户端接收到加密的的值,与自己加密的值相比较,如果一样的话,说明遵循了WebSocket协议。
收发数据
由于是通过socket实现的,先简单的搭建:
后端:
前端:
可以看到后端部分data是接收信息的,可以先看下接收到的信息有什么:
可以看到获取到了很多信息,可以发现很像 http 的请求头之类的东西。我们可以写一个函数对这段信息进行分隔:
def get_headers(data): """ 将请求头格式化成字典 :param data: :return: """ header_dict = {} data = str(data, encoding='utf-8') header, body = data.split('\r\n\r\n', 1) header_list = header.split('\r\n') for i in range(0, len(header_list)): if i == 0: if len(header_list[i].split(' ')) == 3: header_dict['method'], header_dict['url'], header_dict['protocol'] = header_list[i].split(' ') else: k, v = header_list[i].split(':', 1) header_dict[k] = v.strip() return header_dict
分割后的信息:
接着我们就能看到生成的随机字符串:
既然获取到这个值,就可以对它进行加密:
接着:
发送给客户端之后,就要进行对比:
效果:
可以看到成功实现,如果把maigc_srring稍微改动一点,就可以看到链接失败:
客户端发送:
服务端接收:
然后结果:
可以看到这就是我们接收到的东西。
接收到数据以后,需要通过一定的方式才能看到信息。
因为一个字节8位,所以前8个数字代表一个字节。
因为info接收到这些字节,所以 Info[0],就是拿第一个字节。要计算一个字节后四位的值,可以通过 跟 00001111 进行与运算,就能知道相对应的值。
(看上图)
所以 oncode = info[0] & 15
如果我们想要 fin (上图第一个)的值,可以通过拿到第一个字节,向右移动7位,就可以拿到:
fin = info[0] >>7
可以看到payload len占7位。(如果全是1,则最大是127)
所以 payload len的值为:
payload_len = info[1] & 127
重点:payload len的长度会决定往后占多少,后面占几位,payload len说了算。
如果payload len小于126,表示:
表示刚好就这么多位置,后面放数据。
如果payload len等于126:
再往后延伸16位(两个字节)
如果payload len大于126:
往后延伸64位(8个字节)
数据部分的前面4个字节,是masking key,发送的数据已经进行加密,需要通过前面4个字节进行解密。
数据头—masking key—数据
既然知道了原理,就可以进行解包:
info = conn.recv(8096) payload_len = info[1] & 127 if payload_len == 126: extend_payload_len = info[2:4] mask = info[4:8] decoded = info[8:] elif payload_len == 127: extend_payload_len = info[2:10] mask = info[10:14] decoded = info[14:] else: extend_payload_len = None mask = info[2:6] decoded = info[6:] bytes_list = bytearray() for i in range(len(decoded)): chunk = decoded[i] ^ mask[i % 4] bytes_list.append(chunk) body = str(bytes_list, encoding='utf-8') print(body)
能分割开了,就能去解码了(原理):
后端:
然后再次看效果:
就能发现成功接收到数据。
如果字节是一个一个解,则只能解码英文。因为中文是三个三个字节。中文就不要直接解成字符串,中文先解成字节,最后全部都是字节,再统一转换成字符串。所以这里不仅能解码英文,还能解码中文:
如果我们加上一个循环,就能不断接收:
后端:
然后服务端发送消息:
代码:
前端:
效果:
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。