twisted网络框架的三个基础模块:Protocol, ProtocolFactory, Transport.这三个模块是构成twisted服务器端与客户端程序的基本。
Protocol:Protocol对象实现协议内容,即通信的内容协议
ProtocolFactory: 是工厂模式的体现,在这里面生成协议
Transport: 是用来收发数据,服务器端与客户端的数据收发与处理都是基于这个模块
在windows中安装twisted需要先安装pywin32,自己去下载下就行。随后pip install twisted就会帮我们安装twisted以及zope。
我们结合一张图,以及一段程序来理解下twisted的基础实现:
然后我们首先看看服务器端程序:
# coding=utf-8 from twisted.internet.protocol import Protocol from twisted.internet.protocol import Factory from twisted.internet.endpoints import TCP4ServerEndpoint from twisted.internet import reactor clients = [] class Spreader(Protocol): def __init__(self, factory): self.factory = factory def connectionMade(self): self.factory.numProtocols = self.factory.numProtocols + 1 self.transport.write( "欢迎来到Spread Site, 你是第%s个客户端用户!\n" % (self.factory.numProtocols) ) print "new connect: %d" % (self.factory.numProtocols) clients.append(self) def connectionLost(self, reason): self.factory.numProtocols = self.factory.numProtocols - 1 clients.remove(self) print "lost connect: %d" % (self.factory.numProtocols) def dataReceived(self, data): if data == "close": self.transport.loseConnection() for client in clients: if client != self: client.transport.write(data) else: print data class SpreadFactory(Factory): def __init__(self): self.numProtocols = 0 def buildProtocol(self, addr): return Spreader(self) endpoint = TCP4ServerEndpoint(reactor, 8007) endpoint.listen(SpreadFactory()) reactor.run()
创建一个TCP的IPv4版本的终结点,随后就开始监听listen, 在这里我们传入协议工厂对象作为参数, 先看看我们自定义的工厂类SpreadFactory, 它派生自Factory, 我们看看这个类的源码(此时你需要有道词典了:) ):
@implementer(interfaces.IProtocolFactory, interfaces.ILoggingContext) @_oldStyle class Factory: """ This is a factory which produces protocols. By default, buildProtocol will create a protocol of the class given in self.protocol. """ # put a subclass of Protocol here: protocol = None numPorts = 0 noisy = True @classmethod def forProtocol(cls, protocol, *args, **kwargs): """ Create a factory for the given protocol. It sets the C{protocol} attribute and returns the constructed factory instance. @param protocol: A L{Protocol} subclass @param args: Positional arguments for the factory. @param kwargs: Keyword arguments for the factory. @return: A L{Factory} instance wired up to C{protocol}. """ factory = cls(*args, **kwargs) factory.protocol = protocol return factory def logPrefix(self): """ Describe this factory for log messages. """ return self.__class__.__name__ def doStart(self): """Make sure startFactory is called. Users should not call this function themselves! """ if not self.numPorts: if self.noisy: _loggerFor(self).info("Starting factory {factory!r}", factory=self) self.startFactory() self.numPorts = self.numPorts + 1 def doStop(self): """Make sure stopFactory is called. Users should not call this function themselves! """ if self.numPorts == 0: # this shouldn't happen, but does sometimes and this is better # than blowing up in assert as we did previously. return self.numPorts = self.numPorts - 1 if not self.numPorts: if self.noisy: _loggerFor(self).info("Stopping factory {factory!r}", factory=self) self.stopFactory() def startFactory(self): """This will be called before I begin listening on a Port or Connector. It will only be called once, even if the factory is connected to multiple ports. This can be used to perform 'unserialization' tasks that are best put off until things are actually running, such as connecting to a database, opening files, etcetera. """ def stopFactory(self): """This will be called before I stop listening on all Ports/Connectors. This can be overridden to perform 'shutdown' tasks such as disconnecting database connections, closing files, etc. It will be called, for example, before an application shuts down, if it was connected to a port. User code should not call this function directly. """ def buildProtocol(self, addr): """ Create an instance of a subclass of Protocol. The returned instance will handle input on an incoming server connection, and an attribute "factory" pointing to the creating factory. Alternatively, L{None} may be returned to immediately close the new connection. Override this method to alter how Protocol instances get created. @param addr: an object implementing L{twisted.internet.interfaces.IAddress} """ p = self.protocol() p.factory = self return p
在这里很重要的一个函数就是buildProtocol, 此函数就是在工厂模式中创建协议的.我们是基于基类Factory来实现这个函数的, 下面我们看看派生自Protocol的协议类Spread,Spread的__Init__参数中,我们给它传入的是自定义的SpreadFactory, 然后我们看下基类Protocol的源代码