Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.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
挂在Socket.recv上的Python双向TCP套接字_Python_Python 2.7_Sockets_Tcp_Recv - Fatal编程技术网

挂在Socket.recv上的Python双向TCP套接字

挂在Socket.recv上的Python双向TCP套接字,python,python-2.7,sockets,tcp,recv,Python,Python 2.7,Sockets,Tcp,Recv,参考这个例子(和):我试图通过使用TCP阻塞客户机和服务器之间的套接字来实现双向通信 我可以通过客户端->服务器或服务器->客户端进行单向通信,但当尝试在服务器和客户端上接收消息时,套接字仍然被阻止或“挂起”。我正在使用一个简单的算法(recvall),它使用recv,将数据包合并到完整的消息中 我知道在发送或读取所有数据之前,套接字都会被设计阻塞(对吗?),但这不就是sendall和recvall要解决的问题吗?为什么在客户端或服务器上禁用recv“解锁”它并使其工作?我到底做错了什么,导致插

参考这个例子(和):我试图通过使用TCP阻塞客户机和服务器之间的套接字来实现双向通信

我可以通过
客户端->服务器
服务器->客户端
进行单向通信,但当尝试在服务器和客户端上接收消息时,套接字仍然被阻止或“挂起”。我正在使用一个简单的算法(
recvall
),它使用
recv
,将数据包合并到完整的消息中

我知道在发送或读取所有数据之前,套接字都会被设计阻塞(对吗?),但这不就是
sendall
recvall
要解决的问题吗?为什么在客户端或服务器上禁用
recv
“解锁”它并使其工作?我到底做错了什么,导致插座一直被阻塞

这是我的代码,唯一的根本区别是发送的消息:

recvall(套接字)
(在客户端和服务器之间共享):

server.py
(先运行):

client.py
: 导入套接字

s = socket.create_connection((args.ip, args.port))

try:
    s.sendall('hello server')
    print recvall(s)
finally:
    s.close()
根据我的理解(),主要问题是
recv
内部
recvall
只涉及检索流(同样地
send
只涉及发送流),它没有“消息”的概念,因此不知道何时完成读取。它读取了所有字节,没有返回任何额外的字节,但这并不是消息发送完成的信号,可能还有更多的字节等待发送,否则就不安全了

这就要求我们有一个明确的指标来指示何时停止阅读
recv
send
只涉及流的管理,因此没有消息(我们的“单元”)的概念。对这个问题有一些很好的解决办法。因为我发送的是固定长度的消息,所以在完成
recv
之前,我选择检查长度是否符合预期。以下是更新版本的
recvall
,注意
MSG_LENGTH
必须定义并强制执行,以便
recvall
不阻塞套接字

def recvall(socket):
    data = ''
    while len(data) < MSG_LENGTH:
        packet = socket.recv(BUFFER_SIZE)
        if not packet: break
        data += packet
    return data
def recvall(插座):
数据=“”
而len(data)

双向通信现在可以工作了,唯一的问题是客户端和服务器必须知道他们将收到的消息的长度,在我的情况下,这也不是问题。这对我来说是全新的,所以有人请纠正我的术语和概念。

您的recvall()函数将累积所有数据,直到TCP连接关闭,这可能是您的程序出现挂起的原因-您没有关闭连接,因此另一端不知道它应该停止读取。(还请记住,在TCP中,没有数据包-您只得到一个字节流)。因此,您可能需要某种发送数据长度的方法,以便您的recvall()函数可以知道要读取多少数据,或者发送一些特殊的内容来结束数据(例如换行符),并让recvall()查找这些特殊数据。如果我必须关闭套接字,然后重新打开它以便从中读取数据,那么这些数据不会丢失吗?它不是连在插座上吗?或者相反,我必须知道消息的大小(我是在试图避免这种情况)?我认为这是
recvall
的重点,它可以一直读取,直到没有更多的字节通过。然后它知道数据已经完成。我不明白为什么这个例子应该是有效的,但这段代码不是。它们几乎是一样的。recvall()不知道您已经发送了“hello client”或“hello server”,这就是您想要发送的全部内容,它会一直按您所说的方式读取,直到没有更多的字节通过,唯一能确知不会有更多字节通过的方法是关闭TCP连接。如果希望recvall()函数在不关闭连接的情况下停止读取,则必须教会它何时停止读取,例如先发送一个长度,然后在读取了那么多字节后让它停止,或者让它停止读取,例如,当它读取换行符时,或者当它读取了固定数量的字节时让它停止
s = socket.create_connection((args.ip, args.port))

try:
    s.sendall('hello server')
    print recvall(s)
finally:
    s.close()
def recvall(socket):
    data = ''
    while len(data) < MSG_LENGTH:
        packet = socket.recv(BUFFER_SIZE)
        if not packet: break
        data += packet
    return data