# 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. 原理剖析-Netty之服务端启动工作原理分析(上)

    一.大致介绍 1.Netty这个词,对于熟悉并发的童鞋一点都不陌生,它是一个异步事件驱动型的网络通信框架: 2.使用Netty不需要我们关注过多NIO的API操作,简简单单的使用即可,非常方便,开发门 ...

  2. 2 semantic ui 框架的应用

    为什么使用css框架 1.使用基础样式 :  ui segment 分段:内容片段 <link rel="stylesheet" href="css/semanti ...

  3. Python语法之com[1][:-7]

    strCom = com[0] + ": " + com[1][:-7] 如上应该是一个字符串合成,最后的[1][:-7],我理解是去除com[1]的最后7个字符. 比如com[0 ...

  4. 《Cracking the Coding Interview》——第5章:位操作——题目3

    2014-03-19 05:57 题目:给定一个整数N,求出比N大,而且二进制表示中和N有相同个数的‘1’的最小的数,比如3是‘11’,接下来的5是‘101’,再接下来的6是‘110’. 解法:从低位 ...

  5. web前端开发总结(未完)

    由于我也是接触前端开发不久,所以呢,自己也会做点小功课,于是,我把前端能够用到的知识稍稍做了下总结,总结的不全面,以后会慢慢完善的! 移动前端开发基础 (总结----待完善)1.移动前端开发:简而言之 ...

  6. node express 登录拦截器 request接口请求

    1.拦截器 拦截器可以根据需要 做权限拦截 登录只是权限的一种, 思路是req.session.user判断用户session是否存在,是否是需要拦截的地址, 如果是就跳转登录页,或其他页, 如果非需 ...

  7. Canvas 图片绕边旋转的小动画

    /** * 图片绕边旋转的小动画 */ function initDemo10() { var canvas = document.getElementById("demo10") ...

  8. ubantu 系统常见问题

    1 搜狗输入法错误: 删除home路径下的 .config/SouGouP...整个文件夹并重启 2  ubantu系统更新:sudo apt-get update  获取最近更新的软件包列表     ...

  9. 原始套接字--icmp相关

    icmp请求 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <uni ...

  10. reinterpret_cast and const_cast

    reinterpret_cast reinterpret意为“重新解释” reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符.它让程序员能够将一种对象类型转换为另一种,不 ...