TCp传输粘包问题

解决TCP网络传输“粘包”问题
 
当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API)。TCP/IP传输层有两个并列的协
议:TCP和UDP。其中TCP(transport control
protocol,传输控制协议)是面向连接的,提供高可靠性服务UDP(user datagram
protocol,用户数据报协议)是无连接的,提供高效率服务。在实际工程应用中,对可靠性和效率的选择取决于应用的环境和需求。一般情况下,普通数据
的网络传输采用高效率的udp,重要数据的网络传输采用高可靠性的TCP。
在应用开发过程中,笔者发现基于TCP网络传输的应用程序有时会出现粘包现象(即发送方发送的若干包数据到接收方接收时粘成一包)。针对这种情
况,我们进行了专题研究与实验。本文重点分析了TCP网络粘包问题,并结合实验结果提出了解决该问题的对策和方法,供有关工程技术人员参考。
一、TCP协议简介
  TCP是一个面向连接的传输层协议,虽然TCP不属于iso制定的协议集,但由于其在商业界和工业界的成功应用,它已成为事实上的网络标准,广泛应用于各种网络主机间的通信。
  作为一个面向连接的传输层协议,TCP的目标是为用户提供可靠的端到端连接,保证信息有序无误的传输。它除了提供基本的数据传输功能外,还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号,并请求接收方回传确认信息(ack)。发送方如果在规定
的时间内没有收到数据确认,就重传该数据。数据编号使接收方能够处理数据的失序和重复问题。数据误码问题通过在每个传输的数据段中增加校验和予以解决,接收方在接收到数据后检查校验和,若校验和有误,则丢弃该有误码的数据段,并要求发送方重传。流量控制也是保证可靠性的一个重要措施,若无流控,可能会因接收缓冲区溢出而丢失大量数据,导致许多重传,造成网络拥塞恶性循环。TCP采用可变窗口进行流量控制,由接收方控制发送方发送的数据量。
  TCP为用户提供了高可靠性的网络传输服务,但可靠性保障措施也影响了传输效率。因此,在实际工程应用中,只有关键数据的传输才采用TCP,而普通数据的传输一般采用高效率的udp。
二、粘包问题分析与对策
  TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
  出现粘包现象的原因是多方面的,它既可能由发送方造成也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据(图1所示)。


图1


图2


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


图4
  2.实验硬件环境:
  服务器:pentium 350 微机
  客户机:pentium 166微机
  网络平台:由10兆共享式hub连接而成的局域网
  3.实验软件环境:
  操作系统:windows 98
  编程语言:visual c++ 5.0
  4.主要线程
  编程采用多线程方式,服务器端共有两个线程:发送数据线程、发送统计显示线程。客户端共有三个线程:接收数据线程、接收预处理粘包线程、接收统
计显示线程。其中,发送和接收线程优先级设为thread_priority_time_critical(最高优先级),预处理线程优先级为
thread_priority_above_normal(高于普通优先级),显示线程优先级为thread_priority_normal(普通优
先级)。
  实验发送数据的数据结构如图5所示:


图5
  5.分包算法
  针对三种不同的粘包现象,分包算法分别采取了相应的解决办法。其基本思路是首先将待处理的接收数据流(长度设为m)强行转换成预定的结构数据形式,并从中取出结构数据长度字段,即图5中的n,而后根据n计算得到第一包数据长度。
  1)若nm,则表明数据流内容尚不够构成一完整结构数据,需留待与下一包数据合并后再行处理。
  对分包算法具体内容及软件实现有兴趣者,可与作者联系。
四、实验结果分析
  实验结果如下:
  1.在上述实验环境下,当发送方连续发送的若干包数据长度之和小于1500b时,常会出现粘包现象,接收方经预处理线程处理后能正确解开粘在一
起的包。若程序中设置了“发送不延迟”:(setsockopt
(socket_name,ipproto_tcp,tcp_nodelay,(char *) &on,sizeof on)
,其中on=1),则不存在粘包现象。
  2.当发送数据为每包1kb~2kb的不定长数据时,若发送间隔时间小于10ms,偶尔会出现粘包,接收方经预处理线程处理后能正确解开粘在一起的包。
  3.为测定处理粘包的时间,发送方依次循环发送长度为1.5kb、1.9kb、1.2kb、1.6kb、1.0kb数据,共计1000包。为制
造粘包现象,接收线程每次接收前都等待10ms,接收缓冲区设为5000b,结果接收方收到526包数据,其中长度为5000b的有175包。经预处理线
程处理可得到1000包正确数据,粘包处理总时间小于1ms。
  实验结果表明,TCP粘包现象确实存在,但可通过接收方的预处理予以解决,而且处理时间非常短(实验中1000包数据总共处理时间不到1ms),几乎不影响应用程序的正常工作。
               

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AtomicIntegerArray和AtomicIntegerFieldUpdater

2019独角兽企业重金招聘Python工程师标准>>> AtomicIntegerArray 对int数组中元素的操作不是原子性的,所以存在并发操作时,我们应该使用AtomicIntegerArray类来代替int数组。 下面是验证演示代码: public class AtomicIntegerArra…

CMOS图像传感器——高动态范围

动态范围是CMOS 图像传感器中很重要的一项评价指标。动态范围指示了CMOS 图像传感器能够在同一帧图像中同时探测到的最大光强信号和最小光强信号的范围。动态范围通常用dB 形式来表示,其计算公式如下 其中Pmax 和Pmin 分别是最大非饱和光强与最小可探测光强。对于线性…

《Linux内核设计与实现》读书笔记(七)- 中断处理

中断处理一般不是纯软件来实现的,需要硬件的支持。通过对中断的学习有助于更深入的了解系统的一些底层原理,特别是驱动程序的开发。 主要内容: 什么是中断中断类型中断相关函数中断处理机制中断控制方法总结1. 什么是中断 为了提高CPU和外围硬…

入门视频采集与处理(学会分析YUV数据)

标签:分析码流 视频采集 RGB YUV 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/555791做视频采集与处理,自然少不了要学会分析…

数字后端——时序验证

时序验证则是采用时序分析等方法验证设计是否满足时序收敛,这些时序检验工作包括反向标定(back-annotation)、时序与功耗的检验、时序与信号完整性的检验和当代低功耗纳米先进设计中的“多模式多端角”(MMMC,multi-mode multi-comer)检验。 一、反向标定…

Hadoop系列(三)MapReduce Job的几种提交运行模式

Job执行可以分为本地执行或者集群执行。hadoop集群安装部署在远程centos系统中。使用经典的WordCount代码为例。 1. 本地执行模式(本地为MacOS环境),无需启动远程的hadoop集群,本地job会提交给本地执行器LocalJobRunner去执行。 1…

常见视频接口介绍,VGA,YPbPr,DVI,HDMI,DisplayPort

1,VGA(D-SUB) 这种是显示器最常见的,用了很多年,色域空间是RGB,也就是红绿蓝,模拟信号,无音频 插头是15针的,实际所需的最小针数应该是5针,也就是RGB三色信号,水平…

芯片面积估计方法

一、概念 芯片面积的主要涵盖部分分为三部分 IO:芯片的信号及电源pad等Standard cell : 实现芯片的功能逻辑Macro block :第三方IP( PLL DAC POR Memory .etc )芯片面积估计就是通过目标工艺的库信息,设计的spec、以往设计的信息及&#xff…

WordPress开发之WP Custom Register Login插件试用

简介 WP Custom Register Login可以为你的WordPress网站前台增加注册、登录、找回密码的功能;你可以通过简码在任何页面上调用。此外,该插件还支持设置自动通过用户的电子邮件验证新帐户激活,自带算术验证码,有效防护垃圾注册。对…

Java数据类型(基本数据类型)学习

Java数据类型(基本数据类型)学习 与其他语言一样,Java编程同样存在,比如int a,float b等。在学习变量之前我就必须先了解Java的数据类型啦。 Java的数据类型包括基本数据类型和引用数据类型。具体如下: 各数…

SLVS-EC接口学习

SLVS summarize 一、概述 SLVS-EC高速串行接口技术,在CIS和DSP(数字信号处理器)之间实现了高帧率的宽带像素数据传输。 SLVS-EC引入了一个优化的数据包格式和控制协议,几乎没有冗余,而且结构简单,仅由两层…

关于Unity中NGUI的Pivot和锚点

Pivot 1.创建一个Sprite类型的Sprite1节点,关联一个图集和一张贴图,用图中的六个按钮调整这个贴图的Pivot点,一共有八个点可以选择 2.再创建一个Sprite类型的Sprite2节点,作为Sprite1节点的子节点,关联一个图集和一张贴…

PrimeTime指南——概述和基本流程

PrimeTime(PT)是Synopsys的sign-off quality的静态时序分析工具。PrimeTime可以集成于逻辑综合和物理综合的流程,让设计者分析并解决复杂的时序问题,并提高时序收敛的速度。 一、概述 PT最大的两个特点是: 基于时序路…

Android开发——RecyclerView特性以及基本使用方法(二)

0. 前言随着Android的发展,虽然ListView依旧重要,但RecyclerView确实越来越多的被大家使用。但显然并不能说RecyclerView就一定优于ListView,而是应该根据不同的需求选择最合适的进行使用。本篇将介绍我们为什么要使用RecyclerView&#xff…

pycharm中使用scrapy命命

2019独角兽企业重金招聘Python工程师标准>>> 这篇博客写的不错,亲测 https://blog.csdn.net/MAOZEXIJR/article/details/80678133 转载于:https://my.oschina.net/u/2511906/blog/1934993

PrimeTime指南——合理设置约束

完整的STA需要满足以下两点: 完整的设计约束(完整并不意味着正确)运行所有需要的时序检查可以用以下两条命令来进行完整性的检查: check_timing // 检查是否缺少了约束条件 report_analysis_cove…

tablayout支持改变选中文字大小,支持左右滑动,支持viewpager,支持三角可移动指示器...

TabLayout [简书地址] (https://www.jianshu.com/p/2c3f868266e8) 基于大神的FlycoTabLayout [传送地址和基本用法](https://github.com/H07000223/FlycoTabLayout) 用法和属性和这个库一样 效果图如下 主要添加一个属性 tl_text_select_size 控制选中文字大小 看代码截图 然后…

Design Compiler指南——概述和基本流程

综合是前端模块设计中的重要步骤之一,综合的过程是将行为描述的电路、RTL级的电路转换到门级的过程;Design Compiler是Synopsys公司用于做电路综合的核心工具,它可以方便地将HDL语言描述的电路转换到基于工艺库的门级网表。本文将简单介绍综合…

linux常用网络命令

关键词:linux网络命令、ifconfig、route、ip、netstat、socket flag 引言: 想成为真正的高手,必须要熟练掌握linux系统的命令行操作,今天就回顾一下linux在网络上的常用命令相关知识, 另外,实践才是最终的方…

javaweb(三十八)——mysql事务和锁InnoDB(扩展)

MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有同事咨询这方面的问题。同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题。本文,准备就MySQL/InnoDB的加锁问题&…