// 部分一
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函数来开始服务器。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
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的服务器例子:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
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实例
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
# -*- 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例子,与前文不相关
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
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()