诗歌下载服务器html
到目前为止,咱们已经学习了大量关于诗歌下载客户端的Twisted的知识,接下来,咱们使用Twisted从新实现咱们的服务器端。利益于Twisted的抽象机制,接下来你会发现咱们前面已经几乎所有学习到这部分知识了。其实现源码在twisted-server-1/fastpoetry.py中。之因此称其为fastpoetry是由于其并无任何延迟的传输诗歌。注意到,其代码量比客户端少多了。python
让咱们一部分一部分地来看服务端的实现,首先是poetryProtocol:react
class PoetryProtocol(Protocol): def connectionMade(self): self.transport.write(self.factory.poem) self.transport.loseConnection()
如同客户端的实现,服务器端使用Protocol来管理链接(在这里,链接是由客户端发起的)。这里的Protocol实现了咱们的诗歌下载逻辑的服务器端。因为咱们协议逻辑处理的是单向的,服务器端的Protocol只负责发送数据。若是你访问服务器端,协议请求服务器在链接创建后当即发送诗歌,所以我实现了connectionMade方法,其会在Protocol中建立一个链接时被激活执行。git
这个方法告诉Transport作两件事:将整首诗歌发送出去而后关闭链接。固然,这两个动做都是同步操做。所以调用write函数也能够说成“必定要将整首诗歌发送到客户端”,调用loseConnection意味着“一旦将要求下载的诗歌发送完毕就关掉这个链接”。github
也许你看到了,Protocol是从Factory中得到诗歌内容的:服务器
class PoetryFactory(ServerFactory): protocol = PoetryProtocol def __init__(self, poem): self.poem = poem
这么简单!除了建立PoetryProtocol工厂的仅有的工做是存储要发送的诗歌。网络
注意到咱们继承了ServerFactory而不是ClientFactory。这是由于服务器是要被动地监听链接状态而不是像客户端同样去主动的建立。咱们何以如此确定呢?由于咱们使用了listenTCP方法,其描述文档声明factory参数必须是ServerFactory类型的。socket
咱们在main函数中调用了listenTCP函数:函数
def main(): options, poetry_file = parse_args() poem = open(poetry_file).read() factory = PoetryFactory(poem) from twisted.internet import reactor port = reactor.listenTCP(options.port or 0, factory,nterface=options.iface) print 'Serving %s on %s.' % (poetry_file, port.getHost()) reactor.run()
其作了三件事:学习
1.读取咱们要发呈现的诗歌
2.建立PoetryFactory并传入这首诗歌
3.使用listenTCP来让Twisted监听指定的端口,并使用咱们提供的factory来为每一个链接建立一个protocol
剩下的工做就是reactor来运转事件循环了。你可使用前面任何一个客户端来测试这个服务器。
讨论
回忆下第五部分中的图8与图9.这两张图说明了一个协议在Twisted建立一个链接后如何建立一个协议并初始化它的。其实对于Twisted在其监听的端口处接听到一个链接以后的整个处理机制也是如此。这也是为何connectTCP与listenTCP都须要一个factory参数的缘由。
咱们在图9中没有展现是的,connectionMake其实也是Protocol初始化的一部分。不管在哪儿都同样(Dave是想说,connectionMade都会在Protocol初始化时执行),但咱们在客户端处没有用到这个方法。而且咱们在客户端的协议实现中的方法并无在服务器处用到。所以,若是咱们有这个须要,能够建立一个共享式的单一PoetryProtocol供客户端与服务器端使用。这各方式在Twisted常常见到。例如,NetstringReceiver protocol即能读从一个链接中读也能向一个链接中写netstrings。
咱们略去了写从低层来实现服务器端的内容,但咱们仍要来思考一下下面发生的事情。首先,调用listenTCP来告诉Twisted建立一个 listening socket 并将其添加到事件循环中。在 listening socket 有事件发生并不意味有数据要读,而是说明有客户端在等待链接本身。
Twisted会自动接受链接请求,并建立一个新客户端式链接来链接客户端与服务器(中间桥梁)。这个新的链接也要加入事件循环中,而且Twisted为其建立了一个Transport与一个专门为这个链接服务的PoetryProtocol。所以,Protocol实例老是链接到客户端式的socket,而不是监听式socket。
咱们能够在图26中形象地看到这一结果:
图26:服务器端的网络链接
在图中,有三个客户端链接到服务器。每一个Transport表明一个client socket,加上listening socket总共是四个被select循环监听的文件描述符(file descriptor).当一个客户端断开与其相关的transport的链接时,对应的PoetryProtocol也会被解引用并看成垃圾被回收。而PoetryFactory只要咱们还在监听新的链接就会一直不停地工做(即PoetryFactory不会将PoetryProtocol会随着一个链接的断开而被销毁)。
若是咱们提供的诗歌很短的话,那么这些client socket与其相关的各类对象的生命期也就很短。但也有可能会是一台至关繁忙的服务器以致于同时有千百个客户端同时请求较长的诗歌。那不要紧,由于Twisted并无链接创建的限制。固然,当下载量持续的增长,在某个结点处,你会发现已经到达了OS的上限。对于那些高下载量的服务器,仔细的检测与测试是天天都必须的工做。
而且Twisted在监听端口的数量上亦无限制。实际上,一个单一的Twisted线程能够监听数个端口并为其提供不一样的服务(经过使用不一样的factory做为listenTCP的参数便可)。而且通过精心的设计,使用一个Twisted线程来提供多个服务仍是使用多个Twisted线程来实现能够推迟到部署阶段来作决定。
咱们这个版本的服务器有些功能是没有的。首先,它没法产生任何日志来帮助咱们调试和分析网络出现的问题。另外,服务器也不是作为一个守护进程来运行,很容易经过ctrl+c来停止其执行。咱们将会在第十二部分来分析这部份内容。