Python socket 中的recv函数 | 发送长消息

本文探讨了在TCP通信中,如何通过预发送消息长度和利用模运算技巧避免粘包问题,以及针对消息长度为1024倍数的改进策略。作者通过实例展示了两种解决方案的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题描述

        因为需要发送一条超过1024字节的消息,但是recv函数的缓冲区被设为1024字节(以太网的MTU为1500字节,不能设置得更大),所以需要循环接收缓冲区的消息并拼接。

total_data = b''
   
data = client.recv(1024)
while data:
    # 将收到的数据拼接起来
    total_data += data
    data = client.recv(1024)  # 程序会阻塞在这里,并等待另一端发送消息

        上网看了两种解决方案,一是预先把消息的长度发送给服务端,另一个是双方商议一个消息结尾(比如消息末尾加上end)。后者感觉不太行,万一消息结尾刚好被截断,程序就进入了死循环,还可能会出现要发送的消息中出现end的情况。于是选用第一个方案。

二、解决方案

        预先把要发送消息的长度发送给服务端,听起来很容易,其实是不太容易的,直接用send发送完长度再发消息,容易出现粘包问题,为发送的消息写一个头部还需要提取头部,非常麻烦。

        后来想到密码学中模的概念,每次缓冲区提取1024个字节,然后把剩下的提取出来,那么,当剩下的消息长度小于1024,不就代表后面没有消息了?

三、实验结果

初始版本

# 客户端发送消息

client.sendall(message)
# 服务端接收消息
total_data = bytes()
while True:
   # 将收到的数据拼接起来
   data = self.client.recv(1024)
   total_data += data
   if len(data) < 1024:
      break

最后成功打印出客户端发送的长消息。 

但是评论区的网友@Python zzy提出了消息长度刚好是1024的倍数会阻塞的情况,所以针对这种情况进行了改进。

改进版本

# 客户端发送消息
if len(message) % 1024 == 0:
    message = message + b' ' # 比如加上空格,根据自己实际需求更改

client.sendall(message)

服务端保持原样:

# 服务端接收消息
total_data = bytes()
while True:
   # 将收到的数据拼接起来
   data = self.client.recv(1024)
   total_data += data
   if len(data) < 1024:
      break

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值