Python3+WebSockets实现WebSocket通信
一、说明
1.1 背景说明
前端时间同事说云平台通信使用了一个websocket的东西,今天抽空来看一下具体是怎么个通信过程。
从形式上看,websocket是一个应用层协议,socket是数据链路层、网络层、传输层的抽象;从应用场合上看,websocket可以使用javascript实现,而socket不能用javascript实现;从实际效果上看,和一般的socket连接用起来没什么区别。
我们知道http是短连接的,反复建立和销毁连接比较耗费资源,另外http协议经常头部内容比主体内容还长也比较浪费资源;websocket可以认为是一个内容使用载荷固定格式的socket长连接。
websocket基本协议格式如下,更多说明见RFC 6455:

1.2 环境说明
当前环境我使用Python3+WebSockets库,WebSockets直接使用pip安装即可:
pip install websockets
二、代码实现
长连接是有状态的,所以一般在且只在最开始进行一次身份认证,而后通信过程是不需要认证信息。我们这里实现一个简单的用户名密码认证过程。长连接更多内容可参考"长连接与短连接的安全差异讨论 ”。
另外,注意把代码中的ip改成自己的。
2.1 python服务端代码
import asyncio
import websockets# 检测客户端权限,用户名密码通过才能推出循环
async def check_permit(websocket):while True:recv_str = await websocket.recv()cred_dict = recv_str.split(":")if cred_dict[0] == "admin" and cred_dict[1] == "123456":response_str = "congratulation, you have connect with server\r\nnow, you can do something else"await websocket.send(response_str)return Trueelse:response_str = "sorry, the username or password is wrong, please submit again"await websocket.send(response_str)# 接收客户端消息并处理,这里只是简单把客户端发来的返回回去
async def recv_msg(websocket):while True:recv_text = await websocket.recv()response_text = f"your submit context:{recv_text}"await websocket.send(response_text)# 服务器端主逻辑
async def main_logic(websocket, path):await check_permit(websocket)await recv_msg(websocket)start_server = websockets.serve(main_logic, '10.10.6.91', 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
2.2 python版客户端代码
import asyncio
import websockets# 向服务器端认证,用户名密码通过才能退出循环
async def auth_system(websocket):while True:cred_text = input("please enter your username and password:")await websocket.send(cred_text)response_str = await websocket.recv()if "congratulation' in response_str:return True# 向服务器端发送认证后的消息
async def send_msg(websocket):while True:_text = input("please enter your context:")if _text == "exit":print(f'you have enter "exit", goodbye')await websocket.close(reason="user exit")return Falseawait websocket.send(_text)recv_text = await websocket.recv()print(f"{recv_text}")# 客户端主逻辑
async def main_logic():async with websockets.connect('ws://10.10.6.91:5678') as websocket:await auth_system(websocket)await send_msg(websocket)asyncio.get_event_loop().run_until_complete(main_logic())
2.3 html版客户端代码
html版客户端代码,只能通过回调函数接收服务端返回的数据,不能主动接收,感觉怪怪的。
websocket通信客户端
三、通信数据包截获及通信过程分析
以下数据包基于上边的python服务端和html版客户端,再次强调注意把代码中的ip改成自己电脑当前的ip。
3.1 wireshark通信数据包截获及通信过程分析
wireshark拦截数据包后可使用过滤器表达式"websocket"进行过滤:

我们追踪数据流可以更清晰地看清websocket的通信过程,可以看到先是用http完成了建立连接,然后切换到websocket协议。

再看具体数据流也确实如此,先用两个http包建立连接,而后是websocket通信.

3.2 burpsuite通信数据包截获及通信过程分析
和正常配置代理即可,burpsuite能识别和拦截websocket数据包,如下图:

不过和一般http请求有区别的是,websocket请求会被单独汇总到“WebSocket history”选项卡,而不是和http请求混在"HTTP history"选项卡。

3.3 开发者工具通信数据包截获及通信过程分析
FIreFox开发者工具只能看到简历websocket连接的两个http数据包,没看到怎么查看具体传输内容,Chrome开发者工具Frames选项卡可以,如下:

参考:
https://websockets.readthedocs.io/en/stable/intro.html
https://www.runoob.com/html/html5-websocket.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
