Python 中的 recv()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13771937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 09:33:23  来源:igfitidea点击:

recv() in Python

pythonsockets

提问by user1779374

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)

Now I know this is simple server code that can handle a few clients - the only thing that I don't understand are these two lines:

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

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

I understand that when the client has already accepted it will go to the other option, the option that checks if there is something in the buffer. I didn't understand why, when there is nothing in the buffer, it goes on and doesn't check the line:

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

if data == "":

but when the client just presses enter which is equivalent to ""it disconnects

但是当客户端按回车键时,相当于""断开连接

Why when nothing is pressed it is not the same as ""?

为什么当没有按下任何东西时它与""?

采纳答案by GargantuChet

It starts with the selectcall. This function watches sets sockets and waits for something noteworthy to happen. For sockets in the first list, "noteworthy" means that the socket has data available for reading.

它从select呼叫开始。此函数监视设置套接字并等待值得注意的事情发生。对于第一个列表中的套接字,“值得注意”意味着该套接字具有可供读取的数据。

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

The code now iterates through the list of sockets with data ready for reading, and acts based on the type of socket being handled.

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

    for i in rlist:
        if i is listening_socket:

Connection-oriented ("listening") sockets are used to accept new connections. Since it's in rlist, we know it has something for us to "read". In the context of a listening sockets, this means that a new connection has been received. So we accept the connection, and save the new socket in the list of open_sockets.

面向连接(“侦听”)套接字用于接受新连接。由于它在 中rlist,我们知道它有一些东西可供我们“阅读”。在侦听套接字的上下文中,这意味着已收到新连接。所以我们接受连接,并将新的套接字保存在open_sockets.

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

If the socket is not listening_socket, then it's a socket which is (or was) connected to a remote client. And again since it's in rlist, we know that it has something for us to "read". In the context of connected sockets, this means either that data is actually available to be read, or that the socket has been closed.

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

So we call recvto get any available data,

所以我们打电话recv来获取任何可用的数据,

        else:
            data = i.recv(1024)

and see if we've actually read anything. If no data was available, then the connection must have been closed, so we close the socket object and remove it from open_sockets.

看看我们是否真的读过任何东西。如果没有数据可用,那么连接肯定已经关闭,因此我们关闭套接字对象并将其从open_sockets.

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

If we actually did receive data, we just write it back to the client and print it on the screen.

如果我们确实收到了数据,我们只需将其写回客户端并打印在屏幕上。

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

The first call to selectwill wait until a connection is received. You can see for yourself by updating the code as

第一次调用select将等待,直到收到连接。您可以通过将代码更新为自己来查看

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

After the first call, rlistwill include listening_socket. We know this because open_socketsis empty, and as called selectwill not return until something is read to 'read'. So we accept the new connection and add it to open_sockets.

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

When selectis called again, there are three possible events. First, listening_socketmight have received another connection. In this case it is handled as before: we accept the connection and add it to open_sockets.

select再次调用时,有三种可能的事件。首先,listening_socket可能已经收到另一个连接。在这种情况下,它像以前一样处理:我们接受连接并将其添加到open_sockets.

Second, the new connection could have received data. Since selectincluded it in rlist, we know there is data ready to be "read" from the socket (meaning that data is ready for reading, or the socket has been closed). i.recvwill return the new data.

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

Third, the new connection could have been closed. Since selectincluded it in rlist, we know there is data ready to be read from the socket (with the same meaning as above). But i.recvwill return "" since the socket doesn't have any new data. So we know the socket has been closed, and clean up accordingly.

第三,新连接可能已关闭。既然select包含在 中rlist,我们就知道有数据可以从套接字中读取(意义同上)。但是i.recv会返回 "" 因为套接字没有任何新数据。所以我们知道套接字已经关闭,并相应地清理。

If no data is sent from the client (and the connection is still open), then selectwill not include it in rlist. So the loop will not process it, and i.recvwon't be called on that particular socket.

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

回答by Anorov

When a socket sends ""in response, that generally means the socket is closed (or shutdown?). Someone correct me if I'm wrong here. Without that statement, it could become caught in an infinite loop if the remote server suddenly stops responding.

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

回答by jfs

i(btw, an unfortunate name for a socket) won't be in the rlistunless there is something to read i.e., i.recv(1024)will return somethingor the connection is done i.e., i.recv(1024)returns b"".

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

Once .recv()returned b""you won't receive anything from this socket.

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

The interpretation of "the client (a human) just presses enter" depends on the client (software). It has nothing to do with the server e.g., the client can buffer input strings until a newline is encountered or a timeout happened or it can send each byte as soon as it receives it from a user, etc.

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

回答by Gunjan

[root@pa ]# grep "banner_timeout = " /opt/panel-migrator/thirdparties/python/lib/python2.7/site-packages/paramiko/transport.py

self.banner_timeout = 60        # how long (seconds) to wait for the SSH banner