You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.1 KiB
111 lines
4.1 KiB
import logging
|
|
import socket
|
|
import threading
|
|
from unittest import case
|
|
|
|
from models.msg import Msg
|
|
|
|
|
|
class TcpSer(threading.Thread):
|
|
# 定义服务器地址和端口
|
|
HOST = '127.0.0.1'
|
|
PORT = 2230
|
|
def __init__(self,host,port):
|
|
super().__init__()
|
|
self.HOST=host
|
|
self.PORT=port
|
|
self.connected_clients=[]
|
|
# 消费者
|
|
self.consumers=[]
|
|
self.lock = threading.Lock()
|
|
# 处理客户端连接的函数
|
|
def handle_client(self,client_socket):
|
|
try:
|
|
# 当客户端连接时,将其添加到列表中
|
|
self.connected_clients.append(client_socket)
|
|
print(f"新连接: {client_socket.getpeername()}")
|
|
|
|
# 保持连接,直到客户端断开
|
|
while True:
|
|
# 接收客户端数据(如果需要)
|
|
data = client_socket.recv(1024)
|
|
msg_str=data.decode('utf-8')
|
|
if not data:
|
|
break # 如果没有数据,退出循环
|
|
print(f"从 {client_socket.getpeername()} 收到: {msg_str}")
|
|
# 反序列化为 实例
|
|
s_cmd = Msg.from_json(msg_str)
|
|
match s_cmd.cmd:
|
|
case "getPoints" | "setPoints":
|
|
self.on_data(s_cmd)
|
|
# todo 添加处理
|
|
case "xxxxx":
|
|
self.on_data(s_cmd)
|
|
|
|
except Exception as e:
|
|
print(f"处理客户端时出错: {e}")
|
|
finally:
|
|
# 从列表中移除客户端并关闭连接
|
|
if client_socket in self.connected_clients:
|
|
self.connected_clients.remove(client_socket)
|
|
print(f"连接关闭: {client_socket.getpeername()}")
|
|
client_socket.close()
|
|
|
|
# 注册的消费者必须携带on_data 方法
|
|
def add_subscribe(self,consumer):
|
|
if hasattr(consumer, 'on_data'):
|
|
print(f"加入 consumer {consumer} ")
|
|
self.consumers.append(consumer)
|
|
else:
|
|
print("consumer 缺少on_data函数,订阅无效 ")
|
|
def on_data(self,msg):
|
|
for consumer in self.consumers:
|
|
try:
|
|
resp=consumer.on_data(msg)
|
|
self.broadcast_message(resp)
|
|
except Exception as e:
|
|
logging.warn("通讯异常",e)
|
|
|
|
# 广播消息给所有连接的客户端
|
|
def broadcast_message(self,message:str):
|
|
with self.lock:
|
|
if len(message)==0:
|
|
return
|
|
|
|
for client in self.connected_clients:
|
|
try:
|
|
client.sendall(message.encode())
|
|
except Exception as e:
|
|
print(f"向客户端发送消息时出错: {e}")
|
|
# 如果发送失败,从列表中移除客户端
|
|
if client in self.connected_clients:
|
|
self.connected_clients.remove(client)
|
|
client.close()
|
|
def run(self):
|
|
# 创建服务器套接字
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
|
|
server_socket.bind((self.HOST,self.PORT))
|
|
server_socket.listen()
|
|
print(f"服务器监听在 {self.HOST}:{self.PORT}...")
|
|
|
|
try:
|
|
# 保持服务器运行并接受新的连接
|
|
while True:
|
|
client_socket, addr = server_socket.accept()
|
|
print(f"连接来自 {addr}")
|
|
|
|
# 为每个客户端启动一个线程
|
|
client_thread = threading.Thread(target=self.handle_client, args=(client_socket,))
|
|
client_thread.daemon = True # 守护线程,服务器关闭时自动结束
|
|
client_thread.start()
|
|
|
|
except KeyboardInterrupt:
|
|
print("服务器关闭...")
|
|
finally:
|
|
# 关闭所有客户端连接
|
|
for client in self.connected_clients:
|
|
client.close()
|
|
server_socket.close()
|
|
if __name__ == '__main__':
|
|
tcp=TcpSer("127.0.0.1",2230)
|
|
tcp.run()
|