【问题标题】:Retrieving unpack requires a buffer of 8 bytes error socket python检索解包需要8字节的缓冲区错误套接字python
【发布时间】:2020-11-04 18:25:17
【问题描述】:

我有以下代码,我将中间预测结果从客户端发送到服务器。

客户

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = 'localhost'
print('HOST IP:', host_ip)
port = 9999
socket_address = (host_ip, port)
server_socket.bind(socket_address)
server_socket.listen(5)
while True:
    client_socket, addr = server_socket.accept()
    print('GOT CONNECTION FROM:', addr)
    if client_socket:
        vid = cv2.VideoCapture("D:/testing.mp4")
        while (vid.isOpened()):
            img, frame = vid.read()
            image = img_to_array(frame)
            image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
            image = preprocess_input(image)
            preds = model.predict(image)
            a = pickle.dumps(preds)
            message = struct.pack("Q", len(a)) + a
        client_socket.sendall(message)
client_socket.close()

服务器

    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host_ip = 'localhost'
    port = 9999
    client_socket.connect((host_ip, port))
    data = b""
    payload_size = struct.calcsize("Q")
    while True:
        while len(data) < payload_size:
            packet = client_socket.recv(4 * 1024)
            if not packet: break
            data += packet
        packed_msg_size = data[:payload_size]
        data = data[payload_size:]
        msg_size = struct.unpack("Q", packed_msg_size)[0]
        while len(data) < msg_size:
            data += client_socket.recv(4 * 1024)
        frame_data = data[:msg_size]
        data = data[msg_size:]
        frame = pickle.loads(frame_data)

在运行上述代码时,我遇到以下错误

msg_size = struct.unpack("Q", packed_msg_size)[0] struct.error: unpack 需要 8 个字节的缓冲区

谢谢

【问题讨论】:

  • 您的内部 while 循环中的 if not packet: break 没有足够远 - 如果连接在您收到 8 个字节的数据之前关闭,那么您不能继续使用外部 @987654325 @,因为它不会起作用。

标签: python python-3.x sockets struct python-sockets


【解决方案1】:

您还没有解决正常的连接结束问题。如 cmets 中所述,当客户端关闭连接时,您点击 if not packet: break 但这只会使您脱离内部循环,并且您继续尝试处理不存在的消息。那里还有另一个错误,您没有清除每条消息的data

当嵌套循环时,尤其是在通信中发现处理结束几个步骤时,我发现最好将工作分解为具有更狭窄定义角色的多个函数。在这里,您希望一次只接收一条消息,将其构建到 python 对象中,然后使用它。 3 种功能,3 种功能。

def do_the_things():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host_ip = 'localhost'
    port = 9999
    client_socket.connect((host_ip, port))
    while True:
        frame = recv_frame(client_socket)
        if frame is None:
            break

payload_size = struct.calcsize("Q")
    
def recv_obj(client_socket):
    data = recvall(client_socket, payload_size)
    if len(data) < payload_size:
        if not data:
            # client closed after last message, assume all is well
            return None
        else:
            raise IOError("Truncated message")
    packed_msg_size = data[:payload_size]
    data = data[payload_size:]
    msg_size = struct.unpack("Q", packed_msg_size)[0]
    remaining_data = recvall(client_socket, msg_size)
    if len(remaining_data) < msg_size:
        raise IOError("Truncated message")
    obj = pickle.loads(data + remaining_data)
    return obj

def recvall(sock, count):
    """Keep receiving up to `count` bytes, returning partial result
    if connection closed normally by remote."""
    data_bufs = []
    while count:
        data = sock.recv(count)
        if not data:
            break
        count -= len(data)
        data_bufs.append(data)
    return b"".join(data_bufs)

【讨论】:

  • 非常感谢您的精彩建议及其非常有帮助的@tdelaney。我只想说,当我尝试运行您的代码时,服务器关闭了与客户端的连接,甚至没有接收到数据。
  • 客户端运行正常吗? while (vid.isOpened()): ...也许它永远不会打开?也许引发了异常?在那里撒上一些打印件,告诉你发送了什么。顺便说一句,看起来 client_socket.close() 应该缩进到外循环内。
  • 嗨@tdelaney,当 (vid.isOpened()) 没有被打开时,你是对的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2022-10-24
  • 2021-10-06
  • 1970-01-01
相关资源
最近更新 更多