阻塞套接字并选择

Posted

技术标签:

【中文标题】阻塞套接字并选择【英文标题】:blocking sockets and select 【发布时间】:2011-02-23 13:20:21 【问题描述】:

我在玩套接字,我对在 select 中使用阻塞套接字有一些疑问。假设我只是在跟踪潜在的读者。我是否认为 select 将通过列表中的第一个套接字,如果有一些数据可用,它将返回,如果没有,它将阻塞直到 select 的超时到期?读取列表中的其他套接字什么时候会被select检查?

为了简单起见,我用一个python例子来说明:

servsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
servsock.bind(("", 2500))
servsock.listen(15)
servsock.setblocking(1)

readlist = [servsock]

while 1:
    (sread, swrite, sexc) =  select.select(readlist, [], [] ); 

    for sock in sread:

        #received a connect to the server socket
        if  sock == servsock:

        (newsock, address) = servsock.accept()
            newsock.setblocking(1)
            print "I got a connection from ", address
            readlist.append(newsock)
            newsock.send("you're connected to the select server")
        else:
            recv_msg = sock.recv(5)

            if recv_msg == "":
                (host, port) = sock.getpeername()
                print "Client %s:%s closed the connection" % (host,port)
                sock.close()
                readlist.remove(sock)
            else:
                (host, port) = sock.getpeername()
                print "client %s:%s sent: %s "% (host,port,recv_msg)

由于它们是阻塞套接字,所以在测试时会选择总是阻塞,以查看列表中的套接字是否有数据要读取?

【问题讨论】:

【参考方案1】:

select() C API 返回当前可读的所有套接字的列表。假设 python 的包装器也这样做,如果多个套接字是可读的,sread 将包含多个元素。

阻塞套接字只会在没有数据存在的情况下阻塞,因此在select() 调用指示有数据之后,您可以假设一个recv 的调用不会阻塞。

【讨论】:

所以换句话说,选择阻塞和非阻塞套接字的工作方式相同? 是的,它只告诉您数据是否可用,而不是告诉您读取是否会阻塞。如果数据可用,则读取通常不会阻塞,即使这意味着返回的数据少于recv() 的属性要求的数据。【参考方案2】:

select() 将阻塞,直到其中一个套接字有数据。它不仅检查第一个,还检查readlist 变量中的所有内容。

for sock in sread: 中,它遍历所有要读取数据的套接字。

【讨论】:

以上是关于阻塞套接字并选择的主要内容,如果未能解决你的问题,请参考以下文章

阻塞套接字 - 检测状态

用于线程间通信的 Windows 套接字

java套接字/输出流写入:它们阻塞吗?

套接字:为啥阻塞 read() 会因 ENOTCONN 而失败?

如何将 TCP 套接字更改为非阻塞?

windows下的IO模型之选择(select)模型