简介
WebSocket 是一种基于 TCP 协议的通信协议,能够在客户端与服务器之间进行全双工(双向)通信。相比传统的 HTTP 协议,WebSocket 可以实现实时数据的传输,尤其适合需要实时交互的应用场景,如在线游戏、实时聊天、金融交易等。
我通过 Python 实现一个简单的 WebSocket 服务器,并使其与客户端进行通信。我们将创建两个 Python 文件:websocket.py
和 main.py
,websocket.py
负责实现 WebSocket 服务器的功能,main.py
负责启动和管理服务器,以及定时向客户端发送消息。
安装 WebSocket 库
在开始之前,需要安装 websockets
库,它是 Python 中非常流行的 WebSocket 实现。
python
pip install websockets
websocket.py
--- WebSocket 服务器实现
在 websocket.py
文件中,我定义了一个 WebSocketServer
类,包含了 WebSocket 服务器的主要逻辑。
代码解析
python
import asyncio
import websockets
class WebSocketServer:
def __init__(self, host="localhost", port=8765):
self.host = host
self.port = port
self.clients = set() # 存储所有连接的客户端
首先,我创建了一个 WebSocketServer
类,它的构造方法初始化了服务器的主机地址 host
和端口号 port
,同时维护了一个客户端集合 clients
来存储当前连接的 WebSocket 客户端。
python
async def handle_client(self, websocket):
# 新的客户端连接
self.clients.add(websocket)
try:
async for message in websocket:
print(f"收到消息: {message}")
# 回显消息给客户端
await websocket.send(f"服务器已收到: {message}")
except websockets.ConnectionClosed as e:
print(f"客户端断开连接: {e}")
finally:
# 移除断开的客户端
self.clients.remove(websocket)
handle_client
是一个异步方法,用来处理与客户端的连接。在客户端发送消息时,服务器会接收到该消息,并通过 websocket.send()
方法将回显消息发送给客户端。如果客户端断开连接,捕获到 ConnectionClosed
异常,并从 clients
集合中移除该客户端。
python
async def send(self, message):
"""向所有连接的客户端发送消息"""
if not self.clients:
print("没有客户端连接,无法发送消息")
return
disconnected_clients = set()
for client in self.clients:
try:
await client.send(message)
except websockets.ConnectionClosed:
disconnected_clients.add(client)
# 清理已断开的客户端
self.clients -= disconnected_clients
send
方法允许服务器向所有连接的客户端发送消息。如果有客户端断开连接,服务器会将其从 clients
集合中移除。
python
async def start(self):
print(f"启动 WebSocket 服务器: ws://{self.host}:{self.port}")
async with websockets.serve(self.handle_client, self.host, self.port):
await asyncio.Future() # 持续运行直到手动停止
start
方法启动 WebSocket 服务器,通过 websockets.serve()
启动一个 WebSocket 服务,该服务会监听来自客户端的连接请求,并调用 handle_client
方法处理这些请求。await asyncio.Future()
会让服务器持续运行,直到手动停止。
main.py
--- 启动 WebSocket 服务器并定时发送消息
在 main.py
文件中,创建了一个 WebSocket 服务器的实例,并启动了一个定时任务,定期向连接的客户端发送消息。
代码解析
python
import asyncio
from websocket import WebSocketServer
async def main():
# 创建 WebSocket 服务器实例
websocket_server = WebSocketServer()
websocket_task = asyncio.create_task(websocket_server.start()) # 启动 WebSocket 服务器
在 main()
函数中,首先创建了 WebSocketServer
的实例,并启动了 WebSocket 服务器。
python
# 定时向 WebSocket 客户端发送数据
async def send_data_periodically():
while True:
await asyncio.sleep(5) # 每 5 秒发送一次数据
await websocket_server.send("服务器定时发送消息:ping")
send_data_periodically
是一个定时任务,每隔 5 秒就向所有连接的客户端发送一次 "服务器定时发送消息:ping"
。
python
periodic_task = asyncio.create_task(send_data_periodically())
# 并发运行所有任务
await asyncio.gather(websocket_task, periodic_task)
通过 asyncio.create_task()
启动了定时任务,并通过 asyncio.gather()
并发运行 WebSocket 服务器和定时发送消息的任务。
python
if __name__ == "__main__":
asyncio.run(main())
最后,我们 asyncio.run(main())
启动了整个程序。
总结
通过这两个文件,实现了一个简单的 WebSocket 服务器,该服务器能够接收客户端消息并进行回显。同时,服务器也能够定时向所有连接的客户端发送消息。
完整代码
websocket.py
python
import asyncio
import websockets
class WebSocketServer:
def __init__(self, host="localhost", port=8765):
self.host = host
self.port = port
self.clients = set() # 存储所有连接的客户端
async def handle_client(self, websocket):
# 新的客户端连接
self.clients.add(websocket)
try:
async for message in websocket:
print(f"收到消息: {message}")
# 回显消息给客户端
await websocket.send(f"服务器已收到: {message}")
except websockets.ConnectionClosed as e:
print(f"客户端断开连接: {e}")
finally:
# 移除断开的客户端
self.clients.remove(websocket)
async def send(self, message):
"""向所有连接的客户端发送消息"""
if not self.clients:
print("没有客户端连接,无法发送消息")
return
disconnected_clients = set()
for client in self.clients:
try:
await client.send(message)
except websockets.ConnectionClosed:
disconnected_clients.add(client)
# 清理已断开的客户端
self.clients -= disconnected_clients
async def start(self):
print(f"启动 WebSocket 服务器: ws://{self.host}:{self.port}")
async with websockets.serve(self.handle_client, self.host, self.port):
await asyncio.Future() # 持续运行直到手动停止
main.py
python
import asyncio
from websocket import WebSocketServer
async def main():
# 创建 WebSocket 服务器实例
websocket_server = WebSocketServer()
websocket_task = asyncio.create_task(websocket_server.start()) # 启动 WebSocket 服务器
# 定时向 WebSocket 客户端发送数据
async def send_data_periodically():
while True:
await asyncio.sleep(5) # 每 5 秒发送一次数据
await websocket_server.send("服务器定时发送消息:ping")
periodic_task = asyncio.create_task(send_data_periodically())
# 并发运行所有任务
await asyncio.gather(websocket_task, periodic_task)
if __name__ == "__main__":
asyncio.run(main())