套接字线程在超时块中挂起 [英] Socket threads hang in timeout block

查看:53
本文介绍了套接字线程在超时块中挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算从给定套接字接收所有数据所花费的时间,因此我在使用'with Timeout(5,False)'等待5秒钟的数据,然后保存上次接收时间.但是,当我提供多个线程时,当前代码只会停滞不前.我想帮忙弄清楚为什么它应该在超时时挂起.

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()

推荐答案

问题不在于套接字挂起,而是当套接字结束时您永不中断,从而创建了无限循环.这是修复它所需的代码:

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()

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

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()

从gevent文档中获取信息:以0秒为单位调用睡眠是表达合作收益的典型方法."

From the gevent docs: "Calling sleep with seconds of 0 is the canonical way of expressing a cooperative yield."

这篇关于套接字线程在超时块中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆