Python中的recv()

2024-04-19 10:33:52 发布

您现在位置:Python中文网/ 问答频道 /正文

open_sockets = []

listening_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )

listening_socket.bind( ("", 1234) )

listening_socket.listen(5)

while True:
    rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )
    for i in rlist:
        if i is listening_socket:
            new_socket, addr = listening_socket.accept()
            open_sockets.append(new_socket)
        else:
            data = i.recv(1024)
            if data == "":
                i.close()
                open_sockets.remove(i)
                print "Connection closed"
            else:
                i.send(data)
                print repr(data)

现在我知道这是一个简单的服务器代码,可以处理几个客户机—我唯一不明白的是这两行代码:

        data = i.recv(1024)
        if data == "":

我知道,当客户机已经接受时,它将转到另一个选项,即检查缓冲区中是否有内容的选项。我不明白为什么,当缓冲区中没有任何东西时,它会继续运行而不检查行:

if data == "":

但当客户机只需按enter键(相当于"")就会断开连接

为什么当没有东西被按下时,它与""不一样?


Tags: 代码newdata客户机if选项socketopen
3条回答

它从^{}调用开始。这个函数监视设置套接字并等待一些值得注意的事情发生。对于第一个列表中的套接字,“值得注意”意味着套接字具有可供读取的数据。

rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )

现在,代码将遍历具有可供读取的数据的套接字列表,并根据正在处理的套接字类型进行操作。

    for i in rlist:
        if i is listening_socket:

面向连接的(“侦听”)套接字用于接受新连接。因为它在rlist中,我们知道它有一些东西需要我们“阅读”。在侦听套接字的上下文中,这意味着已接收到新连接。因此,我们接受连接,并将新套接字保存在open_sockets列表中。

            new_socket, addr = listening_socket.accept()
            open_sockets.append(new_socket)

如果套接字不是listening_socket,则它是连接到(或曾经连接到)远程客户端的套接字。既然它在rlist中,我们知道它有一些东西可以“阅读”。在已连接套接字的上下文中,这意味着数据实际上可以读取,或者套接字已关闭。

所以我们调用recv来获取任何可用的数据

        else:
            data = i.recv(1024)

看看我们是否真的读过什么。如果没有可用的数据,则连接必须已关闭,因此我们关闭套接字对象并将其从open_sockets中移除。

            if data == "":
                i.close()
                open_sockets.remove(i)
                print "Connection closed"

如果我们真的收到了数据,我们就把它写回客户端并打印到屏幕上。

            else:
                i.send(data)
                print repr(data)

select的第一个调用将等到收到连接。通过更新代码,您可以看到

print "About to call select"
rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )
print "Returned from select"

在第一次调用之后,rlist将包括listening_socket。我们之所以知道这一点,是因为open_sockets是空的,而所谓的select在将某个内容读为“read”之前不会返回。因此,我们接受新连接并将其添加到open_sockets

当再次调用select时,有三种可能的事件。首先,listening_socket可能收到了另一个连接。在本例中,它像以前一样处理:我们接受连接并将其添加到open_sockets

其次,新连接可能已经接收到数据。由于select包含在rlist中,我们知道有数据可以从套接字“读取”(意味着数据可以读取,或者套接字已经关闭)。i.recv将返回新数据。

第三,新的连接可能已经关闭。由于select包含在rlist中,我们知道有数据可以从套接字中读取(具有与上面相同的含义)。但是i.recv将返回“”,因为套接字没有任何新数据。所以我们知道插座已经关闭,并相应地清理。

如果没有从客户端发送数据(并且连接仍处于打开状态),则select将不将其包含在rlist中。所以循环不会处理它,并且i.recv不会在那个特定的套接字上被调用。

i(顺便说一下,一个不幸的套接字名称)不会在rlist中,除非有要读取的内容,即i.recv(1024)将返回something或连接完成,即i.recv(1024)返回b""

一旦.recv()返回b"",您将不会从这个套接字接收任何内容。

“客户(人)按回车”的解释取决于客户(软件)。它与服务器无关,例如,客户机可以缓冲输入字符串,直到遇到换行符或发生超时,或者在收到用户发送的字节后立即发送每个字节,等等

当套接字发送""响应时,通常意味着套接字已关闭(或关闭?)。如果我错了,有人来纠正我。如果没有这个语句,如果远程服务器突然停止响应,它可能会陷入无限循环。

相关问题 更多 >