Python Twisted 框架中 socket通信

本文介绍如何使用Twisted库进行网络编程,包括自定义Protocol处理客户端连接、接收数据及发送消息的方法。通过示例展示了如何搭建一个简易的日志记录服务器,并深入到MMORPG游戏服务器的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// 部分一

Twisted使用了更多的基于事件的方式。要写一个基本的服务器,你要实现事件处理器,它处理诸如一个新的客户端连接、新的数据到达和客户端连接中断等情况。在Twisted中,你的事件处理器定义在一个protocol中;你也需要一个factory,当一个新的连接到达时它能够构造这个protocol对象,但是如果你仅仅想创建一个自定义的Protocol类的实例的话,你可以使用来自Twisted的factory,Factory类在模块twisted.internet.protocol中。当你写你的protocol时,使用twisted.internet.protocol模块中的Protocol作为你的父类。当你得到一个连接时,事件处理器 connectionMade被调用;当你丢失了一个连接时,connectionLost被调用。从客户端接受数据使用处理器 dataReceived。但是你不能使用事件处理策略向客户端发送数据;要向客户端发送数据,你可以使用self.transport,它有一个 write方法。它也有一个client属性,其中包含了客户端的地址(主机名和端口)。

 

下面这个例子是一个Twisted版的服务器。其中实例化了Factory并设置了它的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义 protocol)。然后你使用factory开始监听指定的端口,factory通过实例化的protocol对象处理连接。监听使用reactor模块中的listenTCP函数。最后,你通过调用reactor模块中的run函数来开始服务器。

 

复制代码
from twisted.internet import reactor from twisted.internet.protocol import Protocol, Factory # 定义你Protocol类 class SimpleLogger(Protocol): def connectionMade(self): print 'Got connection from', self.transport.client def connectionLost(self, reason): print self.transport.client, 'disconnected' def dataReceived(self, data): print data # 实例化Factory factory = Factory() # 设置factory的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义 # protocol) factory.protocol = SimpleLogger # 监听指定的端口 reactor.listenTCP(1234, factory) # 开始运行主程序 reactor.run()
复制代码

为你的处理目的而写一个自定义的protocol是很容易的。模块twisted.protocols.basic中包含了几个有用的已存在的 protocol,其中的LineReceiver执行dataReceived并在接受到了一个完整的行时调用事件处理器lineReceived。如果当你在接受数据时除了使用lineReceived,还要做些别的,那么你可以使用LineReceiver定义的名为rawDataReceived 事件处理器。下面是一使用LineReceiver的服务器例子:

 

复制代码
from twisted.internet import reactor from twisted.internet.protocol import Factory from twisted.protocols.basic import LineReceiver class SimpleLogger(LineReceiver): def connectionMade(self): print 'Got connection from', self.transport.client def connectionLost(self, reason): print self.transport.client, 'disconnected' def lineReceived(self, line): print line factory = Factory() factory.protocol = SimpleLogger reactor.listenTCP(1234, factory) reactor.run()
复制代码

 

//部分二: 一个server实例

 

复制代码
# -*- coding: UTF-8 -*- #Twisted MMORPG from twisted.internet.protocol import Factory from twisted.protocols.basic import LineOnlyReceiver from twisted.internet import reactor import random import string class Game(LineOnlyReceiver): def lineReceived(self, data): self.factory.sendAll("%s" % (data)) def getId(self): return str(self.transport.getPeer()) def connectionMade(self): print "New User Login:", self.getId() self.transport.write("欢迎来到MMO世界!\n") self.factory.addClient(self) def connectionLost(self, reason): self.factory.delClient(self) class GameFactory(Factory): protocol = Game def __init__(self): self.clients = [] self.player = [] self.msg='' self.x = range(100,700) self.y = range(100,500) def getPlayerId(self): return len(self.player) def addClient(self, newclient): self.clients.append(newclient) def delClient(self, client): self.clients.remove(client) def sendAll(self, data): #print data if data.find('<policy-file-request/>')!=-1: proto.transport.write('<cross-domain-policy><allow-access-from domain="127.0.0.1" to-ports="*"/></cross-domain-policy>\0') else: arr = data.split(':') prefix = arr[0] content = arr[1] if prefix.find('player')!=-1: newPlayer = [content,str(random.randrange(200, 600)),str(random.randrange(150,350)),str(random.randrange(1,5))] self.player.append(newPlayer) self.msg = ' 玩家 '+content+' 进入游戏!' #广播所有玩家的位置 temp = [] playerData = ':::' for pos in self.player: temp.append(string.join(pos,'---')) playerData = playerData+string.join(temp,'***') for proto in self.clients: proto.transport.write('[系统]: '+self.msg+'\n') proto.transport.write(playerData) elif prefix.find('pos')!=-1: playerName,x,y = content.split('---') i = 0 for p in self.player: if p[0]==playerName: p[1]=x p[2]=y for proto in self.clients: proto.transport.write(data) else: self.msg = data for proto in self.clients: proto.transport.write(self.msg+'\n') reactor.listenTCP(8006, GameFactory()) reactor.run()
复制代码

 

 

// 部分三一个client例子,与前文不相关

复制代码
from twisted.internet.protocol import ClientCreator, Protocol from twisted.protocols.basic import LineReceiver from twisted.internet import reactor import sys class Sender(Protocol): def sendCommand(self, command): print "invio", command self.transport.write(command) def dataReceived(self, data): print "DATA", data PORT = 5005 HOST = 'localhost' def sendCommand(command): def test(d): print "Invio ->", command d.sendCommand(command) c = ClientCreator(reactor, Sender) c.connectTCP(HOST, PORT).addCallback(test) if __name__ == '__main__': if len(sys.argv) != 2 or sys.argv[1] not in ['stop', 'next_call', 'force']: sys.stderr.write('Usage: %s: {stop|next_call|force}\n' % sys.argv[0]) sys.exit(1) sendCommand(sys.argv[1]+'\n') reactor.run()
复制代码
### 使用Python实现简单Socket通信 对于TCP服务器的创建,可以利用内置的Python API来完成这一操作。然而,为了简化过程并增强功能,推荐使用Twisted框架——这是一个专注于网络编程的Python库[^1]。 #### 创建TCP客户端与服务端 下面展示的是通过Python标准库`socket`模块建立基本的TCP连接的例子: ##### TCP Server Example ```python import socket def start_tcp_server(host='127.0.0.1', port=65432): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, port)) s.listen() conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data) start_tcp_server() ``` 这段代码定义了一个函数`start_tcp_server()`用于启动一个监听指定IP地址和端口的服务端程序。当有新的连接请求到来时接受该连接,并进入循环接收来自客户端的数据直到接收到空数据为止,在此期间任何接收到的信息都会被回显给发送方[^2]。 ##### TCP Client Example ```python import socket def tcp_client(message, host='127.0.0.1', port=65432): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) s.sendall(message.encode()) data = s.recv(1024) print(f"Received {data.decode()}") tcp_client("Hello, World!") ``` 这里展示了如何编写一个简单的TCP客户端应用程序。它尝试连接到本地运行的服务端实例并向其发送消息字符串;之后等待响应并将结果打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值