# websocket实现原理
'''
1.服务端开启socket,监听ip和端口
2.客户端发送连接请求(带上ip和端口)
3.服务端允许连接
4.客户端生成一个随机字符串,和magic string组合进行一个sha1加密,加密。并将随机字符串发送给服务端
5.然后服务端也要用相同的方式进行加密。
6.然后服务端将加密之后的密串返回给客户端
7.客户端将服务端返回的密串和自己加密之后的密串进行比对,如果一样,说明遵循同样的协议。如果不一样,就没法玩了·····
''' import socket
import base64
import hashlib
from pprint import pprint 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 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5) # 等待用户连接
conn, addr = server.accept() # 握手消息
content = conn.recv(1024)
'''
>>> print(content) b'GET / HTTP/1.1\r\nHost: localhost:8080\r\nConnection: Upgrade\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\nOrigin: http://localhost:63342\r\nSec-WebSocket-Version: 13\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: uuid=81a68694c772e0c62d4a5a3c256fe3e0; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216453a8bf2bbe-09a40e8e58a866-5e442e19-1fa400-16453a8bf2c745%22%7D; Hm_lvt_2af69bc2b378fb58ae04ed2a04257ed1=1530411925; Pycharm-bdfc5fce=a920e49d-da4e-4d2f-a76e-17acfacc6462\r\nSec-WebSocket-Key: 1y6WpsSgfF80wqi3HpmrqQ==\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n'
''' # 获取请求头
headers = get_headers(content)
'''
>>>pprint(headers)
{'Cache-Control': 'no-cache',
'Connection': 'Upgrade',
'Cookie': 'Pycharm-bdfc5fce=a920e49d-da4e-4d2f-a76e-17acfacc6462',
'Host': 'localhost:8080',
'Origin': 'http://localhost:63342',
'Sec-WebSocket-Key': 'RRGDeYeYSGEP9eHy85u8oQ==',
'Sec-WebSocket-Version': '13',
'Upgrade': 'websocket',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) '
'like Gecko',
'method': 'GET',
'protocol': 'HTTP/1.1',
'url': '/'}
''' # 规定:魔法字符串就叫这个
magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" # 获取随机密串,并将其与魔法字符串组合
value = headers["Sec-WebSocket-Key"] + magic_string # 进行加密,规定,只能按照此加密方式
hash_str = base64.b64encode(hashlib.sha1(bytes(value, encoding='utf-8')).digest()) 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://%s%s\r\n\r\n" # 获取握手消息,组合魔法字符串,进行sha1加密
# 发送给客户端
response_str = response_tpl % (str(hash_str, encoding='utf-8'), headers['Host'], headers['url'])
conn.send(bytes(response_str, encoding='utf-8')) # 也可以发送数据
def send_msg(conn, msg_bytes):
"""
WebSocket服务端向客户端发送消息
:param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
:param msg_bytes: 向客户端发送的字节
:return:
"""
import struct token = b"\x81"
length = len(msg_bytes)
if length < 126:
token += struct.pack("B", length)
elif length <= 0xFFFF:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length) msg = token + msg_bytes
conn.send(msg)
return True # 那么便可以接受数据了,注意接受的数据必须按照一定的规则才能够获取
while True:
info = conn.recv(1024)
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) # 可以将获取的body加上新的字符
body = body + "我是你爸"
send_msg(conn, bytes(body, encoding="utf-8"))

  

  解包过程:(这个图来自于武sir老师的博客:https://www.cnblogs.com/wupeiqi/p/6558766.html)

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+

  

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
ws = new WebSocket("ws://localhost:8080/"); //如果连接成功,会打印下面这句话,否则不会打印
ws.onopen = function () {
console.log('连接成功')
}; //接收数据,服务端有数据过来,会执行
ws.onmessage = function (event) {
console.log(event)
}; //服务端主动断开连接,会执行.
//客户端主动断开的话,不执行
ws.onclose = function () { } </script>
</body>
</html>

  

  

  

python--websocket数据解析的更多相关文章

  1. python爬虫数据解析之BeautifulSoup

    BeautifulSoup是一个可以从HTML或者XML文件中提取数据的python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式. BeautfulSoup是python爬虫三 ...

  2. python爬虫--数据解析

    数据解析 什么是数据解析及作用 概念:就是将一组数据中的局部数据进行提取 作用:来实现聚焦爬虫 数据解析的通用原理 标签定位 取文本或者属性 正则解析 正则回顾 单字符: . : 除换行以外所有字符 ...

  3. Python | JSON 数据解析(Json & JsonPath)

    一.什么是JSON? JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一 ...

  4. python爬虫数据解析的四种不同选择器Xpath,Beautiful Soup,pyquery,re

    这里主要是做一个关于数据爬取以后的数据解析功能的整合,方便查阅,以防混淆 主要讲到的技术有Xpath,BeautifulSoup,PyQuery,re(正则) 首先举出两个作示例的代码,方便后面举例 ...

  5. python爬虫数据解析之正则表达式

    爬虫的一般分为四步,第二个步骤就是对爬取的数据进行解析. python爬虫一般使用三种解析方式,一正则表达式,二xpath,三BeautifulSoup. 这篇博客主要记录下正则表达式的使用. 正则表 ...

  6. python爬虫数据解析之xpath

    xpath是一门在xml文档中查找信息的语言.xpath可以用来在xml文档中对元素和属性进行遍历. 在xpath中,有7中类型的节点,元素,属性,文本,命名空间,处理指令,注释及根节点. 节点 首先 ...

  7. Python—JSON数据解析

    1.安装pip pip是python的包管理工具,使用它能非常方便地安装和卸载各种python工具包 第一步:直接用浏览器访问地址:https://raw.github.com/pypa/pip/ma ...

  8. Python的数据解析

  9. 【Python】 用python实现定时数据解析服务(前言)

    一.Why do it? 背景:项目里上传上来的数据都是未解析的数据,而且数据量还算挺庞大的,每天上传的数据有5kw左右,如果用数据库自带的作业来解析的话,数据库会造成严重的阻塞.因此打算把数据读到外 ...

  10. 精通 Oracle+Python,第 3 部分:数据解析

    进行数据解析的理由不计其数,相关的工具和技巧也同样如此.但是,当您需要用这些数据做一些新的事情时,即使有“合适的”工具可能也是不够的.这一担心对于异类数据源的集成同样存在.用来做这项工作的合适工具迟早 ...

随机推荐

  1. Linux与BSD不同

    https://linux.cn/article-3186-1.html https://www.howtogeek.com/190773/htg-explains-whats-the-differe ...

  2. 4,MongoDB 之 $关键字 及 $修改器 $set $inc $push $pull $pop MongoDB

    MongoDB中的关键字有很多, $lt $gt $lte $gte 等等,这么多我们也不方便记,这里我们说说几个比较常见的 一.查询中常见的 等于 大于 小于 大于等于 小于等于 等于 : 在Mon ...

  3. 3771: Triple

    3771: Triple 链接 题意 n个斧头,每个斧头的价值都不同(开始时没注意到),可以取1个,2个,3个斧头组成不同的价值,求每种价值有多少种组成方案(顺序不同算一种) 分析: 生成函数 + 容 ...

  4. 通俗版解释网关,IP地址,ARP欺骗,DDOS攻击

    计算机主机网关的作用是什么? 假设你的名字叫小不点,你住在一个大院子里,你的邻居有很多小伙伴,在门口传达室还有个看大门的李大爷,李大爷就是你的网关.当你想跟院子里的某个小伙伴玩,只要你在院子里大喊一声 ...

  5. Oz代码梳理

    https://files.cnblogs.com/files/gushiren/oz%E6%B5%81%E7%A8%8B%E5%9B%BE.pdf https://files.cnblogs.com ...

  6. 解决使用vim-go插件时候保存go代码导致设置好的折叠消失的问题

    我之前在用vim编辑python代码的时候,折叠的功能都没啥问题 后来在编辑go代码的时候,我发现我一保存,折叠全都消失了,我很费解,就推断跟我使用的插件有关系,因为我保存的时候会触发gofmt插件格 ...

  7. RMAN 增量备份级别说明

    通过Bat批处理调用RMan是我们定时备份数据库的好帮手,但是RMan的备份级别需要我们好好了解一下. RMAN备份全为全备和增量备份 增量备份:分为0 1 2级 ORACLE官方解释: A leve ...

  8. 团队冲刺Alpha(九)

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...

  9. URAL 1934 spfa算法

    D - Black Spot Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  10. web服务器集群session同步

    在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...