阻塞套接字与选择

1 投票
2 回答
9510 浏览
提问于 2025-04-16 12:23

我正在玩弄套接字(sockets),对使用阻塞套接字和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)

因为它们是阻塞套接字,所以在测试列表中的套接字是否有数据可读时,select会一直阻塞吗?

2 个回答

2

select() 这个函数会一直等待,直到其中一个套接字(也就是网络连接)有数据可以读取。它不是只检查第一个套接字,而是会检查你在 readlist 变量里列出的所有套接字。

for sock in sread: 这行代码中,它会遍历所有有数据可以读取的套接字。

5

select() 是 C 语言中的一个接口,它会返回当前可以读取的所有套接字(也就是网络连接)。假设 Python 的封装也做了类似的事情,那么如果有多个套接字可以读取,sread 就会包含多个元素。

一个阻塞的套接字只有在没有数据时才会阻塞,也就是说,如果在调用 select() 后显示有数据,那么你可以放心地认为,接下来调用一次 recv 不会再阻塞了。

撰写回答