Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的recv()_Python_Sockets - Fatal编程技术网

Python中的recv()

Python中的recv(),python,sockets,Python,Sockets,现在我知道这是一个简单的服务器代码,可以处理一些客户端-我唯一不明白的是以下两行: 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(

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

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 == "":
但是,当客户端只需按enter键(相当于“
)时,它就会断开连接

为什么按nothing时与
不同

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

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

if data == "":
代码现在遍历套接字列表,其中包含准备读取的数据,并根据正在处理的套接字类型进行操作

rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )
面向连接的(“侦听”)套接字用于接受新连接。因为它在
rlist
中,所以我们知道它有一些东西可供我们“阅读”。在侦听套接字的上下文中,这意味着已接收到新连接。因此,我们接受连接,并将新套接字保存在
open\u sockets
列表中

    for i in rlist:
        if i is listening_socket:
        else:
            data = i.recv(1024)
如果套接字不是侦听套接字,则它是连接到(或曾经连接到)远程客户端的套接字。同样,由于它位于
rlist
,我们知道它有一些东西可供我们“阅读”。在已连接套接字的上下文中,这意味着数据实际上可以读取,或者套接字已关闭

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

            new_socket, addr = listening_socket.accept()
            open_sockets.append(new_socket)
看看我们是否真的读过什么。如果没有可用数据,则连接必须已关闭,因此我们关闭套接字对象并将其从
打开的\u sockets中删除

    for i in rlist:
        if i is listening_socket:
        else:
            data = i.recv(1024)
如果我们确实收到了数据,我们只需将其写回客户端并在屏幕上打印

            if data == "":
                i.close()
                open_sockets.remove(i)
                print "Connection closed"
select
的第一次调用将等待收到连接。您可以通过将代码更新为

            else:
                i.send(data)
                print repr(data)
在第一次调用后,
rlist
将包括
侦听\u套接字
。我们之所以知道这一点,是因为
open\u sockets
是空的,而所谓的
select
在将某个内容读取为“read”之前不会返回。因此,我们接受新连接并将其添加到
open\u sockets

    for i in rlist:
        if i is listening_socket:
        else:
            data = i.recv(1024)
再次调用
select
时,有三种可能的事件。首先,
侦听\u socket
可能已接收到另一个连接。在这种情况下,它的处理与以前一样:我们接受连接并将其添加到
open\u sockets

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

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

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

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

一旦
.recv()
返回
b”“
您将不会从该套接字接收任何内容


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

值得一提的是
socket.setblocking()
socket.settimeout()
,我认为,因为严格来说,
recv
会普遍阻塞不是真的。它不会阻塞i
表示
i
已“准备好”阅读。1024是bufsize,recv()可以返回更少字节。我不明白。你说的是,如果不按任何键,它将无法通过线路,因此它将被卡住,无法通过其他客户端,或者你的意思是它将跳过if条件?@J.F.Sebastian,你完全正确。我已经编辑了我的答案。谢谢。@user1779374,请让我知道编辑是否有助于澄清。谢谢这是正确的。这正好发生在我身上,它导致了巨大的内存过载,因为我正在向列表中添加数据以查找终端标记。谢谢你指出这一点。@MichaelDavidWatson一个相当流行的网络库也有一个类似的bug,它在我的代码中造成了混乱的无限循环挂起。一个简单的
如果不是数据:引发异常通常是最好的解决方法。
print "About to call select"
rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )
print "Returned from select"