套接字线程在超时块中挂起

时间:2012-06-12 14:25:23

标签: python sockets gevent

我试图计算从给定套接字接收所有数据所需的时间,因此我使用'使用Timeout(5,False)'等待5秒钟的数据,然后保存上次recv的时间。但是,当我提供多个线程时,当前代码就会停止并挂起。我想帮助弄清楚为什么它会在超时时挂起。

#!/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 个答案:

答案 0 :(得分:3)

问题不在于套接字挂起,而是在套接字结束时永远不会中断,从而产生无限循环。以下是修复它所需的代码:

with Timeout(5, False):
    while 1:
        data = s.recv(1024)
        if not data:
            break

        sock_buffer += data
        stop = time.time()

编辑: 一旦套接字完成连接,即使你正在调用#recv,它也不会产生greenlet线程。因此,如果您希望能够触发超时,则需要使用gevent.sleep()手动生成:

with Timeout(5, False):
    while True:
        data = s.recv(1024)
        if data:
            sock_buffer += data
            stop = time.time()

        gevent.sleep()

来自gevent文档:“用0秒调用睡眠是表达合作产量的规范方式。”