问题
I'm trying to calculate the time it takes to receive all data from a given socket, so I'm using 'with Timeout(5, False)' to wait 5 seconds for data and then save the time of last recv. However, the current code just sits and hangs when I supply more than one thread. I'd like help figuring out why it just hangs when it should timeout.
#!/usr/bin/env python
import sys
import time
from gevent import socket, Timeout
from gevent.pool import Pool
def calc_wait(website):
data = ''
start = stop = time.time()
sock_buffer = ''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((website,80))
s.send('HEAD / HTTP/1.1\n\n')
with Timeout(5, False):
while True:
data = s.recv(1024)
if data:
sock_buffer += data
stop = time.time()
print ('Recieved {0} bytes in {1} seconds from {2}'
.format(len(sock_buffer), stop-start, s.getpeername()))
return 0
if __name__ == "__main__":
targs = ['google.com', 'yahoo.com', 'bing.com',\
'tide.com', 'monkey.com', 'python.com',\
'a.com', 'b.com', 'c.com', 'd.com']
pool = Pool(10)
for t in targs:
pool.spawn(calc_wait, t)
pool.join()
回答1:
The problem is not that the socket hangs but that you never break when the socket ends, creating an infinite loop. Here's the code needed to fix it:
with Timeout(5, False):
while 1:
data = s.recv(1024)
if not data:
break
sock_buffer += data
stop = time.time()
EDIT:
Once the socket completes its connection, it won't yield the greenlet thread even though you're calling #recv
. So if you want the timeout to be able to fire you need to manually yield with gevent.sleep()
:
with Timeout(5, False):
while True:
data = s.recv(1024)
if data:
sock_buffer += data
stop = time.time()
gevent.sleep()
From the gevent docs: "Calling sleep with seconds of 0 is the canonical way of expressing a cooperative yield."
来源:https://stackoverflow.com/questions/10998715/socket-threads-hang-in-timeout-block