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

时间:2017-05-22 20:41:44

标签: python python-2.7 sockets tcp recv

引用此示例(以及docs):https://pymotw.com/2/socket/tcp.html我正在尝试使用TCP实现客户端和服务器之间的阻塞套接字的双向通信。

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

我知道套接字在设计中被阻止,直到所有数据都被发送或读取(对吗?),但不是sendallrecvall处理的内容?为什么在客户端或服务器上禁用recv“解除阻塞”并导致它工作?最终我做错了什么导致套接字被阻止?

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

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

def recvall(socket):
    data = ''
    while True:
        packet = socket.recv(16)
        if not packet: break
        data += packet

    return data

server.py(先跑):

import socket

host = 'localhost'
port = 8080

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)

while True:
    (client, address) = s.accept()
    print 'client connected'

    try:
        print recvall(client)
        client.sendall('hello client')
    finally:
        client.close()

client.py:     导入套接字

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

try:
    s.sendall('hello server')
    print recvall(s)
finally:
    s.close()

1 个答案:

答案 0 :(得分:1)

根据我的理解(epiphany here),主要问题是recv内的recvall仅涉及检索流(同样只关注send通过发送流),它没有"消息的概念"因此无法知道何时完成阅读。它读取所有字节并且没有返回任何额外的字节,但这不是消息完成发送的信号,可能有更多的字节等待发送,否则不安全。

这要求我们有一个明确指示何时停止阅读。 recvsend仅关注管理流,因此没有消息的概念(我们的"单位")。 This article为这个问题提供了一些很好的解决方案。由于我发送固定长度的消息,因此我选择在完成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

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