DIOCP之DEMO-粘包问题及解决

什么是粘包问题?

举个例子:sever发送20480 个A字母,可是由于client一次只收到10240个A,余下的又发送一次:第一个包中包括有此数据包的总长度,读取出长度,然后接收一个对比长度,如果当前长度<包标定长度,那么就等余下包,一直等到足够包长度,把他们组合在一起就算接收一个数据包.

TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。    
出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。

粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包,此处假设用户接收缓冲区长度为m个字节。

不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。    
在处理定长结构数据的粘包问题时,分包算法比较简单;在处理不定长结构数据的粘包问题时,分包算法就比较复杂。特别是如图3所示的粘包情况,由于一包数据内容被分在了两个连续的接收包中,处理起来难度较大。实际工程应用中应尽量避免出现粘包现象。    
为了避免粘包现象,可采取以下几种措施。一是对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;二是对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;三是由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。    
以上提到的三种措施,都有其不足之处。第一种编程设置方法虽然可以避免发送方引起的粘包,但它关闭了优化算法,降低了网络发送效率,影响应用程序的性能,一般不建议使用。第二种方法只能减少出现粘包的可能性,但并不能完全避免粘包,当发送频率较高时,或由于网络突发可能使某个时间段数据包到达接收方较快,接收方还是有可能来不及接收,从而导致粘包。第三种方法虽然避免了粘包,但应用程序的效率较低,对实时应用的场合不适合。    
一种比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。对这种方法我们进行了实验,证明是高效可行的。

解决方案:TLV协议

TLV协议说明:
T(Tag)字段表示数据包类型,传输中定义为short类型;L(length)字段表示数据包长度(不包括类型和长度字段本身),传输中定义为long类型.T和L共同组成包头;V(value)表示数据包信息。

TSendPacket=record //
   PType:Word; //包类型
   PLength:DWORD; //长度
   VehicleInfo:TVehiclePacket; //数据
   end;

时间: 2024-11-10 11:18:17

DIOCP之DEMO-粘包问题及解决的相关文章

20 Apr 18 粘包问题及解决方法

20 Apr 18 一.上节课复习 1. TCP(建立的是一个双向连接)三次握手建连接,四次挥手断连接 三次握手:    c----syn=1 seq=x--->s    s----ack=1+x syn=1 seq=y--->c    c----ack=1+y------->s    四次挥手:    s------fin=1---------->c    c------>ack=1--------->s    c------>fin=1--------->

Socket编程实践(5) --TCP粘包问题与解决

TCP粘包问题 因为TCP协议是基于字节流且无边界的传输协议, 因此非常有可能产生粘包问题, 问题描写叙述例如以下 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvempmMjgwNDQxNTg5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" /> 对于Host A 发送的M1与M2两个各10K的数据块, Host B 接收数据的方式不确定, 有以下

Socket传输简单的信息以及粘包问题的解决

一.简单的socket程序--传输简短文字: # -*- coding: utf-8 -*- # -*- Author: WangHW -*- import socket whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) whw_client.connect(('127.0.0.1',9001)) while 1: cmd = input('>>>:').strip() if not cmd: continue w

python--subprocess,粘包现象与解决办法,缓冲区

一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 stdout=subprocess.PIPE, #标准输出 PIPE 管道,保存着指令的执行结果 stderr=subprocess.PIPE #标准错误输出 ) # dir 当前操作系统(Windows)的命令,会执行stdout print('正确输出',sub_obj.stdout.read().d

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

TCP协议:三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立连接的请求 3:客户端接收到服务端发来的请求,返回接成功给服务端,完成双向连接 第一客戶向服务端发送请求,请求建立连接 服务端同客户端的请求,并同时向客户端发送建立 连接的请求,最后客户端同意后建立 双向连接. C ----> S C <---- S - 反馈机制: 客户端往服务端发送请求,服务端必须返回响应, 告诉客户

python3 tcp的粘包现象和解决办法

服务器端 import socket sk = socket.socket() sk.bind(("127.0.0.1", 6666)) sk.listen() conn, address = sk.accept() def my_send(msg): bs = msg.encode("utf-8") len_str = format(len(bs), "04d") # 定长4位 conn.send(len_str.encode("ut

Socket编程实践(6) --TCP粘包原因与解决

流协议与粘包 粘包的表现 Host A 发送数据给 Host B; 而Host B 接收数据的方式不确定 粘包产生的原因 说明 TCP 字节流,无边界 对等方,一次读操作,不能保证完全把消息读完 UDP 数据报,有边界 对方接受数据包的个数是不确定的 产生粘包问题的原因分析 1.SQ_SNDBUF 套接字本身有缓冲区 (发送缓冲区.接受缓冲区) 2.tcp传送的端 mss大小限制 3.链路层也有MTU大小限制,如果数据包大于>MTU要在IP层进行分片,导致消息分割. 4.tcp的流量控制和拥塞控

【游戏开发】Netty TCP粘包/拆包问题的解决办法(二)

上一篇:[Netty4.X]Unity客户端与Netty服务器的网络通信(一) 一.什么是TCP粘包/拆包 如图所示,假如客户端分别发送两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4中情况: 第一种情况:Server端分别读取到D1和D2,没有产生粘包和拆包的情况. 第二种情况:Server端一次接收到两个数据包,D1和D2粘合在一起,被称为TCP粘包. 第三种情况:Server端分2次读取到2个数据包,第一次读取到D1包和D2包的部分内容D2_1,第二次

tcp套接字粘包解决办法

粘包只会出现在tcp,udp传输不会产生粘包现象.解决粘包的原理就是服务器预先向客户端发送客户端即将获取文件的大小. 第一版解决方案: 服务器: 1 # Author : Kelvin 2 # Date : 2019/2/2 17:38 3 from socket import * 4 import subprocess 5 6 ip_conf = ("127.0.0.1", 8888) 7 buffer_capacity = 1024 8 tcp_server = socket(AF

TCP粘包,拆包及解决方法

粘包拆包问题是处于网络比较底层的问题,在数据链路层.网络层以及传输层都有可能发生.我们日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中. 什么是粘包.拆包? 假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据可以分为三种,现列举如下: 第一种情况,接收端正常收到两个数据包,即没有发生拆包和粘包的现象,此种情况不在本文的讨论范围内. 第二种情况,接收端只收到一个数据包,由于TC