套接字编程 Python:如何确保收到整个消息? [英] Socket Programming Python: How to make sure entire message is received?

查看:34
本文介绍了套接字编程 Python:如何确保收到整个消息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 python 3.x 和 socket 模块.服务器在 ipv4 地址上运行并使用 tcp.我阅读了一些关于如何发送和接收数据的教程.为了让服务器或客户端确保发送了整个消息,您可以简单地检查发送的数据量是否等于消息的大小:

I am using python 3.x and the socket module. The server is running on an ipv4 address and using tcp. I read some tutorials on how to send and receive data. For the server or client to make sure the entire message was sent you can simply check if the amount of sent data is equals the size of the message:

def mysend(self, msg):
    totalsent = 0
    while totalsent < MSGLEN:
        sent = self.sock.send(msg[totalsent:])
        if sent == 0:
            raise RuntimeError("socket connection broken")
        totalsent = totalsent + sent

来源:https://docs.python.org/3/howto/sockets.html#socket-howto

并且让客户端确保已收到整个响应本教程建议在响应的开头添加响应的大小.

And for the client to make sure the entire response has been received this tutorial recommends to add the size of the response at the beginning of the response.

我的问题:

  1. 如何确保我收到消息的第一部分指示消息的大小(假设我的消息包含 1000 个字符,我需要四个字符来指示大小)?
  2. 为什么我不能只添加一个指定的符号,比如<"在消息的乞求和结尾的 '>' 这样我就知道它从哪里开始和结束?

  1. 当我使用 sock.recv(1024) 并且我的消息只有 500 到 1000 个字符时,这不能确保我收到所有消息吗?
  1. When I use sock.recv(1024) and my messages just have a size of 500 to 1000 characters doesn't that make sure I receive all of them?

推荐答案

首先,发送所有字节不需要循环,因为 python sockets 提供了一个简单的方法:socket.sendall().

First of all, to send all the bytes you don't need a loop because python sockets provide a simple method: socket.sendall().

现在回答您的问题:

  1. 是的,即使只接收 4 个字节,您也应该有一个调用 recv() 直到读取 4 个字节.

  1. Yes, even to receive just 4 bytes you should have a receive loop that calls recv() on the socket until 4 bytes are read.

您可以,如果您可以保证此类字符不会出现在消息本身中.但是,您仍然需要搜索读入的每个字符以获取魔法分隔符,因此它似乎不如简单地在消息正文前加上长度前缀.

You can, if you can guarantee that such characters will not appear in the message itself. However, you'd still need to search every character that you read in for the magic delimiter, so it seems inferior to simply prefixing the message body with a length.

当你调用 recv(n) 只保证返回最多 n 个字节,而不是恰好 n 个字节.

When you call recv(n) that is only guaranteed to return at most n bytes, not exactly n bytes.

这里有三种不同的 recvall() 方法进行比较:

Here are three different recvall() methods to compare:

def recvall(sock, size):
    received_chunks = []
    buf_size = 4096
    remaining = size
    while remaining > 0:
        received = sock.recv(min(remaining, buf_size))
        if not received:
            raise Exception('unexpected EOF')
        received_chunks.append(received)
        remaining -= len(received)
    return b''.join(received_chunks)

和更短的

def recvall2(sock, size):
    return sock.recv(size, socket.MSG_WAITALL)

最后的另一个版本比第一个短一点但缺少一些功能:

and finally another version that is a little shorter than the first but lacks a couple of features:

def recvall3(sock, size):
    result = b''
    remaining = size
    while remaining > 0:
        data = sock.recv(remaining)
        result += data
        remaining -= len(data)
    return result

第二个很好而且很短,但它依赖于套接字选项 socket.MSG_WAITALL,我不相信它保证在每个平台上都存在.第一个和第三个应该在任何地方都有效.我还没有真正对任何基准进行比较和对比.

The second one is nice and short, but it relies on a socket option socket.MSG_WAITALL that I do not believe is guaranteed to exist on every platform. The first and third ones should work everywhere. I haven't really benchmarked any to compare and contrast.

这篇关于套接字编程 Python:如何确保收到整个消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆