我正在编写一个扭曲的教程,只是为了学习更多的python,似乎我在这里遇到了障碍。下面的doRead()函数是反应堆的“回调”。我不明白的是除外部分是如何工作的。
我阅读代码的方式是,如果bytes += self.sock.recv(1024)
会导致阻塞,那么它将到达代码的以下部分:
if e.args[0] == errno.EWOULDBLOCK:
break
然后它将继续执行以下操作:
if not bytes:
print 'Task %d finished' % self.task_num
return main.CONNECTION_DONE
else:
msg = 'Task %d: got %d bytes of poetry from %s'
print msg % (self.task_num, len(bytes), self.format_addr())
对我来说,最棘手的部分是,如果它被阻塞了,那么bytes变量将不包含任何内容,并且将被打印为“ finish”,但事实并非如此。或至少它会打印出“获得0字节”之类的信息,但事实并非如此。在我看来,当代码遇到来自recv调用的代码块时,它几乎完全跳过了上面的部分。有人可以解释为什么会这样吗?
输出是这样的:
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 3 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
这是整个功能:
def doRead(self):
bytes = ''
while True:
try:
bytes += self.sock.recv(1024)
if not bytes:
break
except socket.error, e: # I don't understand this part
if e.args[0] == errno.EWOULDBLOCK:
break
return main.CONNECTION_LOST
if not bytes:
print 'Task %d finished' % self.task_num
return main.CONNECTION_DONE
else:
msg = 'Task %d: got %d bytes of poetry from %s'
print msg % (self.task_num, len(bytes), self.format_addr())
self.poem += bytes
整个模块粘贴在这里:http://pastebin.com/bUnXgbCA
最佳答案
关键是,仅当套接字“准备读取”时调用方法doRead
:要么套接字上有一些数据,要么全部完成(然后读取将返回0
)。因此,解决问题的方法不能放在doRead
函数中,而只能在适当的时候才在代码中调用它。
该代码全部在Twisted“反应堆”中,PoetrySocket
实例将自身添加到__init__
中(通过反应堆的addReader
方法)。如果您想真正地了解扭曲的机制,那么顺便说一下,您似乎处在正确的位置(当然,可以自己研究扭曲的源代码;-)。