Websocket优势解析: 双向通信、长连接及实时数据更新
目录

1。为什么使用Websocket? 1.1 Websocket协议简介
WebSocket协议是对HTTP的改进,可以实现客户端和服务器之间的双向通信。建立Websocket连接后,它始终保持维护,直到客户端或服务器中断连接,以弥补缺乏HTTP无法维持长时间连接并促进客户端应用程序和服务器之间的实时通信。
适用的方案
为什么不使用AJAX实时更新数据方案?
Ajax使用HTTP。如果您想实时更新页面,则需要连续发送HTTP请求,无论是否有数据更新,都会导致大量冗余通信流量。 Websocket是一种长期连接的双向通信。有数据更新后,服务器将向客户端发送通知。
1.2基本原则
基于TCP,可以通过握手建立连接,支持双向通信并可以保持长时间的连接。
WebSocket握手请求消息示例::
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
如果服务器收到连接,请返回响应
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
响应代码为101,表明切换到WebSocket协议。
Websocket已得到主流浏览器和编程语言的广泛支持。它基本上提供了Websocket高级编程API。通常,它可以替换低阶套接字功能编程。 Python提供了更简洁的编程实施。以下显示了示例代码方法,并说明了如何开发Python WebSocket Server Code,Python Websocket客户端和JavaScript Websocket代码。
2。如何使用Python构建Websocket服务
Python第三方库Websockets提供了一个Websocket实施框架,支持Asyncio,具有强大的性能和良好的稳定性,可以在生产环境中使用。
2.1安装Websockets软件包
pip install websockets
2.2编写服务器端代码
WebSocket服务器代码是多个用户的长连接,因此本文使用python3.7的异步版本来编写WebSocket服务器代码。
该服务器还可以使用ThreadPoolExecutor线程池方法同时处理多个连接。当有很多用户时,性能显然不如异步异步方法好。
Websockets模块服务器端的主要方法:
实施步骤:
编写Websocket异步任务处理功能处理程序以创建WebSocket Server对象。异步运行服务器对象。
WebSocket地址格式:
以下是特定的代码服务器
#!/usr/bin/python3
# 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求
import asyncio
import websockets
from datetime import datetime
async def handler(websocket):
data = await websocket.recv()
reply = f"Data received as \"{data}\". time: {datetime.now()}"
print(reply)
await websocket.send(reply)
print("Send reply")
async def main():
async with websockets.serve(handler, "localhost", 9999):
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
还有另一种编写服务器处理程序功能代码的方法,这更适用。
async def handler(websocket):
async for message in websocket:
reply = f"Data received as \"{message}\". time: {datetime.now()}"
print(reply)
await websocket.send(reply)
Websocket协议本身具有心跳机制和连接检测机制。服务器不需要关心客户端状态。一旦有例外,它将自动断开连接。
WebSockets提供交互式测试命令,现在您可以快速测试服务器是否可以正常工作:
(1)启动服务器:python server.py
(2)通过命令行连接到服务器,然后向其发送Hello,World Messages。您可以看到已经收到了服务器的响应。
D:\workplace\python\projects\websock>python -m websockets ws://localhost:9999
Connected to ws://localhost:9999.
> hello, world
< Data received as "hello, world". time: 2023-04-01 09:24:14.787357
Connection closed: 1000 (OK).
当然,在实践中应用它时,您应该按照以下步骤编写客户端代码。
3。PythonWebsocket客户端实现代码
Websockets客户端提供的主要方法:
让我们看一下示例client.py
import asyncio
import websockets
import time
async def ws_client(url):
for i in range(1, 40):
async with websockets.connect(url) as websocket:
await websocket.send("Hello, I am PyPy.")
response = await websocket.recv()
print(response)
time.sleep(1)
asyncio.run(ws_client('ws://localhost:9999'))
4。JavaScript Websocket客户端实现代码
当前,主流浏览器支持Websocket协议。
JavaScript Websocket对象的主要属性和方法:
请参阅新秀教程中的这篇文章:
示例代码:client.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>websocket demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"> </script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
function WebSocketTest() {
text = document.getElementById("div_text");
if ("WebSocket" in window) {
// 打开一个 web socket
var ws = new WebSocket("ws://localhost:9999/handler");
ws.onopen = function () {
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("Javscript发送的数据");
text.innerHTML = "数据发送中...";
alert("数据发送中...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
text.innerHTML = "收到的数据:" + received_msg;
alert("数据已接收...");
};
ws.onclose = function () {
// 关闭 websocket
text.innerHTML = "连接已关闭...";
alert("连接已关闭...");
};
}
else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
</script>
</head>
<body>
<div class="col-md-6 m-5 p-2" id="div_ws">
<a class="btn btn-primary" href="javascript:WebSocketTest()">连接WebSocket</a>
</div>
<div class="col-md-6 border border-primary mx-5 p-2 " id="div_text" style="margin:20px;height:100px;">
display communicate text
</div>
</body>
</html>
5。测试Websocket
以上三个文件放在同一目录中。打开两个终端窗口,首先运行server.py,然后运行客户端Py。
输出结果
在Chrome或Edge中运行Client.html,您可以看到Websocket连接建立,发送,接收和关闭阶段的状态。
可以看出,服务器和客户端之间的通信是双向的,并且连接很长。客户端断开连接后,服务器保持侦听,并且不需要接受操作。 WebSocket发送和接收文件,而无需控制发送窗口缓冲区的插座,因此它是插座开发的一个很好的替代方法。
注意:Python asynchronous Websocket服务器的最终性能与代码质量,服务器硬件,网络等密切相关。您可以使用WebSocket-基准测试工具来测试服务器。
6。服务器向客户端广播消息
Websockets模块支持向所有已连接的客户广播消息。
使用一个简单的示例来说明实现步骤:
修改上一个服务器和.py代码如下:
#!/usr/bin/python3
# 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求
import asyncio
import websockets
from datetime import datetime
# Set of connected clients
connected_clients = set()
async def handler(websocket, path):
# Add the client to the connected clients set
connected_clients.add(websocket)
try:
# Keep listening for incoming messages from the client
async for message in websocket:
# Broadcast the message to all connected clients
await broadcast(message)
finally:
connected_clients.remove(websocket)
async def broadcast(message):
# Broadcast the message to all connected clients
for client in connected_clients:
await client.send(message)
async def main():
async with websockets.serve(handler, "localhost", 9998):
await asyncio.Future() # run forever
loop = asyncio.get_running_loop() #获取当前event_loop对象
loop.create_task(broadcast()) # 添加新的异步广播任务
if __name__ == "__main__":
asyncio.run(main())
在此示例中,当服务器收到1条消息时,它将向所有用户广播。
总结
本文主要介绍:
如果项目中的WebSocket通信内容很复杂,并且Websocket并发的数量很高,则可以使用Django-Channels框架。