最近在看twisted,直接在gitbook中找了一本twisted的书籍,虽然书中对代码进行了详细的解释,但是其中的代码不读个三四遍仍然难以理解。故在此把自己的理解记录下来。
先直接上代码与注释。
# This is the Twisted Get Poetry Now! client, version 3.0.
# NOTE: This should not be used as the basis for production code.
import optparse
from twisted.internet.protocol import Protocol, ClientFactory
def parse_args():
# 这个函数不需要深究,就是在处理输入参数。只需要知道它返回了host和port就可以了。
usage = """usage: %prog [options] [hostname]:port ...
This is the Get Poetry Now! client, Twisted version 3.0
Run it like this:
python get-poetry-1.py port1 port2 port3 ...
If you are in the base directory of the twisted-intro package,
you could run it like this:
python twisted-client-3/get-poetry-1.py 10001 10002 10003
to grab poetry from servers on ports 10001, 10002, and 10003.
Of course, there need to be servers listening on those ports
for that to work.
"""
parser = optparse.OptionParser(usage)
_, addresses = parser.parse_args()
if not addresses:
print(parser.format_help())
parser.exit()
def parse_address(addr):
if ':' not in addr:
host = '127.0.0.1'
port = addr
else:
host, port = addr.split(':', 1)
if not port.isdigit():
parser.error('Ports must be integers.')
return host, int(port)
return list(map(parse_address, addresses))
class PoetryProtocol(Protocol):
# 自定义接收协议
poem = ''
def dataReceived(self, data): # 自动接收数据 在data中。
self.poem += data.decode('utf-8')
def connectionLost(self, reason): # 连接断开后要做的事情,此处是调用了PoetryClientFactory的实例中的poem_finished方法。传入了poem
# 可以看出 self.callback(poem)只有poem接收完成后才会调用。而这个callback实际上是传入的get_poem函数。
# 也就是说实际上的回调函数是 get_poem()
self.poemReceived(self.poem)
def poemReceived(self, poem):
self.factory.poem_finished(poem)
class PoetryClientFactory(ClientFactory):
protocol = PoetryProtocol
def __init__(self, callback):
# 传入一个回调函数
self.callback = callback
def poem_finished(self, poem):
# 文本接收完毕后调用该函数。
self.callback(poem)
def get_poetry(host, port, callback):
"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete.
"""
from twisted.internet import reactor
factory = PoetryClientFactory(callback)
reactor.connectTCP(host, port, factory)
def poetry_main():
addresses = parse_args()
from twisted.internet import reactor
poems = []
def got_poem(poem):
poems.append(poem)
if len(poems) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
get_poetry(host, port, got_poem)
reactor.run()
for poem in poems:
print(poem)
if __name__ == '__main__':
poetry_main()
首先,该段代码对参数进行了处理,将所有的address以list的方式保存倒了addresses。
定义回调函数get_poem,当所有的poem接收完毕后,将其保存在poems中,并且当接收的诗歌数量和address的数量相等的时候,关闭reactor循环。
下面,按照我的理解,相当于将addresses中的address注册进reacotr循环中。采用tcp连接的方式,PoetryProtocol协议进行接收数据。