前言:

本文是针对socket长连接(涉及到服务器主动推数据),每个包头的拼接算法和长度都不一样,具体的包头小伙伴们问自己公司的开发吧,本文只是提供思路。再啰嗦一句:recv到的包头中数字进行某种运算后得到的就是开发定义的返回code。

粘包问题解决思路:

python中的socket recv()是阻塞接收的,所以不存在同时发送多个数据接收错乱的情况。网上对于粘包有各种各样的解决办法,什么每次recv前sleep几秒,保证缓存中有足够数据在接收。还有说在recv()中加个wait的参数,保证每次都接受满1024个数据长度。我觉得网上唯一正确的办法是:先知道自己想要接收的数据的大小,然后用一个死循环接收完所有数据。

作者一开始是使用静态拆包的方式,就是每次send后都recv一次,然后把每次recv的结果都拼在一起,然后再根据包头中的包体长度拆出一个个完整包。这种方式有个缺点:如果后面的请求需要用到前面请求返回值做参数,那么就凉凉了。

这时候就需要用到动态拆包,send一个请求recv一个返回结果,然后解析出完整数据。但是实现的过程中发现几个问题:

(1)返回数据的长度跟我从包头里得到的长度不一致,我以为是粘包导致的接收不全,因为我后来加了个一样的请求,就能接收全了。

(2)后来我在每个请求发送前都加了sleep(10),第16个请求接受全了,但是后面的数据直接报错了。

(3)后来偶然一次,我发现能运行成功不报错,但是在大部分时运行会报错。

(4)然后发现send一个请求,返回了两个完整的包。

结合上面的四个问题,我开始了漫长的寻求解答的过程,后来得高人解答,才发现了问题——服务器主动推了数据。现在想想上面4点可不就是服务器主动推数据的表现嘛。

下面直接上方法,同时解决粘包、服务器主动推数据的问题。

思路:send之后,先recv(8)包头,得到包体大小,然后用死循环recv全。然后要用包头算法对得到的返回数据进行判断,进一步保证了这个包就是我需要的数据包。

 1 def sendData(self, data, t, respHeader):
2 self.data = data
3 self.t = t
4 self.respHeader=respHeader
5 self.s.send(data) # 传输包装好的请求
6 total_data = bytes()
7 header = 1
8
9 for i in range(5): #每次send,我规定它最多去recv5次,以防浪费时间
10 header_bytes = self.s.recv(8) # 先接收包头
11 body_len = struct.unpack("!2I", header_bytes)[0] #这是包体长度
12 header = struct.unpack("!2I", header_bytes)[1] #开发定义的用来做运算
13 print("应该接收的长度:", body_len)
14 while len(total_data) < body_len:
15 total_data += self.s.recv(body_len)
16 print("实际接收的长度:", len(total_data))
17 18 header_code = header & 0x3xxxxxxx #做运算得到返回请求的code
19 print("header_code: " + str(header_code))
20 #如果算出来等于这个返回请求的头或者返回error,跳出for循环,不再继续recv
21 if header_code == int(respHeader) or header_code == 1:
22 print("over")
23 break
24    else:
25 #如果接收的不是我需要的包头,清空total_data,重新for循环从缓存中recv数据
26 total_data = bytes()
27 if i >= 5:
28 print("返回数据有误")

一个完整的socket recv()案例,包括解决粘包、服务器主动推数据的问题的更多相关文章

  1. day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信

    day31 recv工作原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自socket缓冲区的字节数据, For the opt ...

  2. 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

    TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...

  3. c# socket 解决粘包,半包

    处理原理: 半包:即一条消息底层分几次发送,先有个头包读取整条消息的长度,当不满足长度时,将消息临时缓存起来,直到满足长度再解码 粘包:两条完整/不完整消息粘在一起,一般是解码完上一条消息,然后再判断 ...

  4. Socket解决粘包问题1

    粘包是指发送端发送的包速度过快,到接收端那边多包并成一个包的现象,比如发送端连续10次发送1个字符'a',因为发送的速度很快,接收端可能一次就收到了10个字符'aaaaaaaaaa',这就是接收端的粘 ...

  5. Python开发【socket篇】解决粘包

    客户端 import os import json import struct import socket sk = socket.socket() sk.connect(('127.0.0.1',8 ...

  6. 网络编程基础【day09】:socket解决粘包问题之MD5(八)

    本节内容 1.概述 2.代码实现 一.概述 上一篇博客讲到的用MD5来校验还是用的之前解决粘包的方法,就是客户端发送一个请求,等待服务端的确认的这样的一个笨方法.下面我们用另外一种方法:就是客户端已经 ...

  7. 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验

    上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...

  8. 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法

    网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) ​ 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...

  9. Dealing with a Stream-based Transport 处理一个基于流的传输 粘包 即使关闭nagle算法,也不能解决粘包问题

    即使关闭nagle算法,也不能解决粘包问题 https://waylau.com/netty-4-user-guide/Getting%20Started/Dealing%20with%20a%20S ...

随机推荐

  1. centos7 安装卸载程序rpm使用方法

    1.安装 rpm 包: ➢ 基本语法 rpm -ivh RPM 包全路径名称 2.卸载 rpm 包: ➢ 基本语法 rpm -e RPM 包的名称 ➢ 应用案例 删除 firefox 软件包 rpm ...

  2. 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?

    目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...

  3. R-常见错误

    错误一:选择了未定义的列(Undefined columns are selected) 改正方法:把目标列转换成因子类型(as.factor) 使用代码如下: 或者: 错误二:太多(36119)的重 ...

  4. 18.自动运维工具ansible

    1 Ansible 介绍和架构 1.1 Ansible介绍 ansible 的名称来自科幻小说<安德的游戏>中跨越时空的即时通信工具,使用它可以在相距数光年的 距离,远程实时控制前线的舰队 ...

  5. noi 162 post office dp

    大致题意: 有v个村庄,每个村庄有各自的位置,且每个位置互不相同.现在要在村庄上设立P个邮局,使每个村庄到最近的邮局的距离之和最小. 分析: 定义状态d[i][j]表示前i个村庄,在这i个村庄中设立j ...

  6. Redis 底层数据结构之整数集合

    文章参考:<Redis 设计与实现>黄建宏 整数集合 整数集合时集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合数量不多时,就会使用整数集合 typedef struct i ...

  7. 毕业季offer怎么拿?收下这份非典型求职面试指南

    摘要:求职面试莫慌,先自我评估一下 ,华为云专家手把手为你指导. 本文分享自华为云社区<毕业季offer怎么拿?收下这份非典型求职面试指南>,原文作者:技术火炬手 . 又是一年毕业季,对于 ...

  8. 关于windows11的0x800f0950语言包安装失败

    最近windows11的风头很热,作为爱折腾的人,当然要去搞一搞啦.搞好了以后我发现中文语言的拓展包是无法安装的,于是我找到了3个办法,当然如果想100%成功的话我建议直接跳到第三个,如果你不嫌累,指 ...

  9. Hadoop:什么是Hadoop??

    官方讲解: Apache Hadoop 为可靠的,可扩展的分布式计算开发开源软件.Apache Hadoop软件库是一个框架,它允许使用简单的编程模型跨计算机群集分布式处理大型数据集(海量的数据). ...

  10. SpringMVC(7)格式化显示

    在SpringMVC(六)数据验证中我们介绍了如何验证提交的数据的正确性,当数据验证通过后就会被我们保存起来.保存的数据会用于以后的展示,这才是保存的价值.那么在展示的时候如何按照要求显示?(比如:小 ...