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

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()