使用Python的Twisted框架实现一个简单的服务器
预览
from twisted.internet.protocol import Protocol class Echo(Protocol): def dataReceived(self,data): self.transport.writed(data) 这是个非常简单的协议处理,仅仅是在获得数据的事件中简单的将接收到的数据发送回去,并没有对所有的事件进行响应。这里有一个Protocol响应其他事件的例子如下: from twisted.internet.protocol import Protocol class QOTD(Protocol): def connectionMade(self): self.transport.write("An apple a day keeps the doctor away/r/n") self.transport.loseConnection() 本Protocl在一个已知的引用刚开始连接上来的时候作出响应,发送了一条消息,然后终止了连接connectionMade事件通常是在由于连接对象建立初始连接时触发,就像上面的QOTD类实际上是RFC865号文档的一个协议基类connectionLost事件将在断开连接的时候触发。实例: <span style="font-family: Monospaced; color: #0000a0;"><strong>PythonCode: </strong></span><table style="width: 100%; height: 20px;" align="center" bgcolor="#e3dfe3" border="1" bordercolor="#9da7ac" cellpadding="0" cellspacing="0"> <tbody><tr><td> <div class="textBackGround" style="font-family:Courier New;font-size:9pt;"><pre><span style="color: blue;">from</span> twisted.internet.protocol <span style="color: blue;">import</span> Protocol <span style="color: blue;">class</span> Echo(Protocol): <span style="color: blue;">def</span> connectionMade(self): self.factory.numProtocols = self.factory.numProtocols+1 <span style="color: blue;">if</span> self.factory.numProtocols > 100: self.transport.write(<span style="color: #ff44a2;">"Too many connections,<span style="color: blue;">try</span> later"</span>) self.transport.loseConnection() <span style="color: blue;">def</span> connectionLost(self,reason): self.factory.numProtocols = self.factory.numProtocols-1 <span style="color: blue;">def</span> dataReceived(self,data): self.transport.write(data)</pre> </div> </td> </tr> </tbody> </table> 本实例中,connectionMade和connectionLost相互协作工作以保持factory内部的活动连接数量最多为100。每当有用户协议连接近来的时候,就先检测factory内部的活动连接数,如果数量超过100,就发送连接数太多等下试的消息,然后断开连接而connectionLost则在断开一个协议的时候触发,减去factory内部的协议数量。 Using the Protocol 在本节,我将要讲解怎样简单的去测试你的protocol。(想知道如何写出一个好的twisted的服务器,请看 <a href="http://fantix.org/twisted-doc-zh/nightly/online/howto/plugin.html">Writing Plug-Ins<br> for Twisted</a>),这里有一个代码将运行我们上面谈论的QOTD服务器: <!-- .textBackGround {background-color: #F0F5FD;} --> <span style="font-family: Monospaced; color: #0000a0;"><strong>PythonCode: </strong></span><table style="width: 100%; height: 20px;" align="center" bgcolor="#e3dfe3" border="1" bordercolor="#9da7ac" cellpadding="0" cellspacing="0"> <tbody><tr><td> <div class="textBackGround" style="font-family:Courier New;font-size:9pt;"><pre><span style="color: blue;">from</span> twisted.internet.protocol <span style="color: blue;">import</span> Protocol,Factory <span style="color: blue;">from</span> twisted.internet <span style="color: blue;">import</span> reactor <span style="color: blue;">class</span> QOTD(Protocol): <span style="color: blue;">def</span> connectionMade(self): self.transport.write(<span style="color: #ff44a2;">"An apple a day keeps the doctor away/r/n"</span>) self.transport.loseConnection() <span style="color: green;"># Next lines are magic:</span> factory = Factory() factory.protocol = QOTD <span style="color: green;"># 8007 <span style="color: blue;">is</span> the port you want to run under. Choose something >1024</span> reactor.listenTCP(8007,factory) reactor.run()</pre> </div> </td> </tr> </tbody> </table> 不必担心最后面的6条代码,稍后你将会在本文档中了解到他们。<br> Helper Protocols 大部分protocols依赖于同类别的更低层次的超级类。最受欢迎的互联网协议是基于行,行通常是由CR_LF(回车换行组成) PythonCode: from twisted.protocols.basic import LineReceiver class Answer(LineReceiver): answers = {'How are you?': 'Fine',None : "I don't know what you mean"} def lineReceived(self,line): if self.answers.has_key(line): self.sendLine(self.answers[line]) else: self.sendLine(self.answers[None]) 注意:界定符不是命令行的一部分 State Machines 许多twisted protocol handlers需要编写一个状态机来记录他们当前的状态,这里有几点编写状态机的建议: Factories(工厂类) 如前面所说,通常twisted.internet.protocol.Factory不必子类化就可以开始工作。然而有时候protocol需要具体的 PythonCode: from twisted.internet.protocol import Factory from twisted.protocols.wire import Echo myFactory = Factory() myFactory.protocol = Echo 如果需要简单的去构造一个有具体特殊信息的工厂类,那么一个factory函数是非常有用的: PythonCode: class QOTD(Protocol): def connectionMade(self): self.transport.write(self.factory.quote+'/r/n') self.transport.loseConnection() def makeQOTDFactory(quote=None): factory = Factory() factory.protocol = QOTD factory.quote = quote or 'An apple a day keeps the doctor away' return factory
一个Factory有两个方法以执行特定于应用程序的建立和拆除(由于一个Factory通常存在,所以常规下一般不在__init__或者 from twisted.internet.protocol import Factory from twisted.protocols.basic import LineReceiver class LoggingProtocol(LineReceiver): def lineReceived(self,line): self.factory.fp.write(line+'/n') class LogfileFactory(Factory): protocol = LoggingProtocol def __init__(self,fileName): self.file = fileName def startFactory(self): self.fp = open(self.file,'a') def stopFactory(self): self.fp.close() Putting it All Together(综合) 现在你已经了解了Factory并且想要执行QOTD作为一个可配置的quote服务器是吗?没有问题这里就有一个代码: from twisted.internet.protocol import Factory,Protocol from twisted.internet import reactor class QOTD(Protocol): def connectionMade(self): self.transport.write(self.factory.quote+'/r/n') self.transport.loseConnection() class QOTDFactory(Factory): protocol = QOTD def __init__(self,quote=None): self.quote = quote or 'An apple a day keeps the doctor away' reactor.listenTCP(8007,QOTDFactory("configurable quote")) reactor.run() 就是最后两句代码,还需要去理解。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |