【Twisted】Python 使用Twisted实现TCP多人聊天Demo
# 导入必要的Twisted模块
from twisted.internet import reactor # 事件循环核心模块
from twisted.internet.protocol import Factory # 用于管理协议实例的工厂类
from twisted.protocols.basic import LineReceiver # 按行接收数据的协议基类# 定义聊天协议类,继承自LineReceiver
class Chat(LineReceiver):def __init__(self, users):"""初始化聊天协议实例:param users: 共享的用户字典(用户名->协议实例)"""self.users = users # 存储所有用户的字典(由Factory共享)self.name = None # 当前连接的用户名(初始为None)self.state = "GETNAME" # 状态机状态:初始为获取用户名阶段def connectionMade(self):"""当客户端连接成功时自动调用"""self.sendLine(b"What's your name?") # 向客户端发送输入用户名提示def connectionLost(self, reason):"""当客户端断开连接时自动调用"""if self.name in self.users:del self.users[self.name] # 从用户字典中移除该用户def lineReceived(self, line):"""当接收到一行数据时自动调用:param line: 接收到的数据行(字节串)"""if self.state == "GETNAME":self.handle_GETNAME(line) # 处理用户名设置阶段else:self.handle_CHAT(line) # 处理聊天消息阶段def handle_GETNAME(self, name):"""处理用户名设置逻辑:param name: 客户端发送的用户名"""if name in self.users:self.sendLine(b"Name taken, please choose another.") # 用户名已存在return# 用户名可用self.sendLine(f"Welcome, {name.decode('utf-8')}!".encode("utf-8")) # 发送欢迎消息self.name = name # 设置当前用户名self.users[name] = self # 将用户添加到共享字典self.state = "CHAT" # 切换到聊天状态def handle_CHAT(self, message):"""处理聊天消息逻辑:param message: 客户端发送的聊天消息"""message = b"<" + self.name + b"> " + message # 格式化消息(添加用户名前缀)# 广播消息给所有其他用户for name, protocol in self.users.items():if protocol != self: # 不发送给自己protocol.sendLine(message)# 定义协议工厂类
class ChatFactory(Factory):def __init__(self):"""初始化工厂实例"""self.users = {} # 创建空字典用于存储用户(用户名->协议实例的映射)def buildProtocol(self, addr):"""为每个新连接创建协议实例:param addr: 客户端地址信息:return: 新的Chat协议实例"""return Chat(self.users) # 创建Chat实例并共享users字典# 主程序入口
if __name__ == "__main__":reactor.listenTCP(8123, ChatFactory()) # 在8123端口监听,使用ChatFactory处理连接reactor.run() # 启动事件循环,开始处理网络事件
使用telnet连接服务:telnet 127.0.0.1 8123