当前位置:  开发笔记 > 编程语言 > 正文

如何获得非阻塞套接字connect()?

如何解决《如何获得非阻塞套接字connect()?》经验,为你挑选了3个好方法。

我这里有一个非常简单的问题.我需要同时与很多主机通信,但我并不需要任何同步,因为每个请求都非常自给自足.

因此,我选择使用异步套接字,而不是发送垃圾邮件.现在我有一点问题:

异步的东西就像魅力一样,但当我连接到100个主机,并且我得到100次超时(超时= 10秒)然后我等待1000秒,只是为了找出我的所有连接都失败了.

有没有办法得到非阻塞套接字连接?我的套接字已设置为nonBlocking,但对connect()的调用仍然是阻塞的.

减少超时是不可接受的解决方案.

我在Python中这样做,但我想在这种情况下编程语言并不重要.

我真的需要使用线程吗?



1> Vinay Sajip..:

使用该select模块.这允许您等待多个非阻塞套接字上的I/O完成.这里有一些关于选择的更多信息.从链接到页面:

在C中,编码select相当复杂.在Python中,它是一块蛋糕,但它与C版本足够接近,如果您理解Python中的select,那么在C语言中你会遇到一些麻烦.

ready_to_read, ready_to_write, in_error = select.select(
                  potential_readers, 
                  potential_writers, 
                  potential_errs, 
                  timeout)

你传递了select三个列表:第一个包含你可能想要尝试阅读的所有套接字; 您可能想要尝试写入的第二个所有套接字,以及要检查错误的最后一个(通常为空).您应该注意,套接字可以进入多个列表.该select呼叫是阻止的,但您可以暂停.这通常是一件明智的事情 - 给它一个很长的超时(比如一分钟),除非你有充分的理由不这样做.

作为回报,您将获得三个列表.它们具有实际可读,可写和错误的套接字.这些列表中的每一个都是您传入的相应列表的子集(可能为空).如果您将套接字放在多个输入列表中,它将只(最多)在一个输出列表中.

如果一个套接字位于输出可读列表中,那么你就可以接近确定这个recv套接字将返回的东西.可写清单的想法相同.你能send 做点什么.也许不是你想要的全部,但有些东西总比没有好.(实际上,任何合理健康的套接字都将返回为可写 - 它只是意味着出站网络缓冲区空间可用.)

如果您有"服务器"套接字,请将其放在potential_readers列表中.如果它出现在可读列表中,那么您的接受(几乎肯定)会起作用.如果您已创建新套接字以连接到其他人,请将其放在potential_writers列表中.如果它出现在可写列表中,那么它有很大的可能性已连接.



2> ebo..:

不幸的是,没有示例代码显示错误,所以有点难以看出这个块来自何处.

他做了类似的事情:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
s.connect(("www.nonexistingname.org", 80))

套接字模块在内部使用getaddrinfo,这是一个阻塞操作,尤其是当主机名不存在时.符合标准的dns客户端将等待一段时间,看看该名称是否确实存在,或者是否只涉及一些慢速DNS服务器.

解决方案是仅连接到ip-addresses或使用允许非阻塞请求的dns客户端,如pydns.



3> JimB..:

您还需要并行化连接,因为设置超时时套接字会阻塞.或者,您无法设置超时,并使用选择模块.

您可以使用asyncore模块中的调度程序类执行此操作.看一下基本的http客户端示例.该类的多个实例不会在连接上相互阻塞.您可以使用线程轻松完成此操作,我认为使跟踪套接字超时更容易,但由于您已经在使用异步方法,因此您也可以保持在同一轨道上.

例如,以下内容适用于我的所有Linux系统

import asyncore, socket

class client(asyncore.dispatcher):
    def __init__(self, host):
        self.host = host
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, 22))

    def handle_connect(self):
        print 'Connected to', self.host

    def handle_close(self):
        self.close()

    def handle_write(self):
        self.send('')

    def handle_read(self):
        print ' ', self.recv(1024)

clients = []
for i in range(50, 100):
    clients.append(client('cluster%d' % i))

asyncore.loop()

在cluster50 - cluster100中,有许多机器没有响应或不存在.这会立即开始打印:

Connected to cluster50
  SSH-2.0-OpenSSH_4.3

Connected to cluster51
  SSH-2.0-OpenSSH_4.3

Connected to cluster52
  SSH-2.0-OpenSSH_4.3

Connected to cluster60
  SSH-2.0-OpenSSH_4.3

Connected to cluster61
  SSH-2.0-OpenSSH_4.3

...

然而,这并未考虑必须阻止的getaddrinfo.如果您在解决dns查询时遇到问题,那么一切都必须等待.您可能需要单独收集dns查询,并在异步循环中使用ip地址

如果你想要一个比asyncore更大的工具包,请看看Twisted Matrix.进入它有点沉重,但它是python可以获得的最好的网络编程工具包.

推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有