TCP通信丢包主要问题及具体问题分析_tcp的客户端发送报文给服务器,不产生丢包或网络阻塞,但是数据不一致是因为-程序员宅基地

技术标签: 网络通信  

  今天在公司问老大,公司的项目底层,是使用的TCP,因为可靠,自动断线重连,在底层都实现了,但是我记得TCP也会有掉包的问题,所以这文章就诞生了——关于TCP掉包的问题,TCP是基于不可靠的网络实现可靠的传输,肯定也会存在掉包的情况。

    如果通信中发现缺少数据或者丢包,那么,最大的可能在于程序发送的过程或者接收的过程出现问题。

    例如服务器给客户端发大量数据,Send的频率很高,那么就有可能在Send时发生错误(原因可能是又多种,可能是程序处理逻辑问题,多线程同步问题,缓冲区溢出问题等等),如果没有对Send失败做处理重发数据,那么客户端收到的数据就会比理论应该收到的少,就会造成丢数据,丢包的现象。
    这种现象,其实本质上来说不是丢包,也不是丢数据,只是因为程序处理有错误,导致有些数据没有成功地被socket发送出去。
 
    常用的解决方法如下:拆包、加包头、发送,组合包,如果客户端、服务端掉线,常采用心跳测试。
 

tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

粘包、拆包问题说明

假设客户端分别发送数据包D1和D2给服务端,由于服务端一次性读取到的字节数是不确定的,所以可能存在以下4种情况。

  • 1.服务端分2次读取到了两个独立的包,分别是D1,D2,没有粘包和拆包;
  • 2.服务端一次性接收了两个包,D1和D2粘在一起了,被成为TCP粘包;
  • 3.服务端分2次读取到了两个数据包,第一次读取到了完整的D1和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为拆包;
  • 4.服务端分2次读取到了两个数据包,第一次读取到了部分D1,第二次读取D1剩余的部分和完整的D2包;

如果此时服务端TCP接收滑动窗非常小,而数据包D1和D2都很大,很有可能发送第五种可能,即服务端多次才能把D1和D2接收完全,期间多次发生拆包情况。(TCP接收滑动窗:是接收端的大小,随着流量大小而变化,如果我的解释还不明确,请读者自行百度,或者查阅《计算机网络》、《TCP/IP》中TCP的内容)

粘包问题的解决策略

由于底层的TCP无法理解上层的业务逻辑,所以在底层是无法确保数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:

  • 1.消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格;
  • 2.在包尾增加回车换行符进行分割,例如FTP协议;
  • 3.将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常设计思路是消息头的第一个字段用int来表示消息的总长度;(我之前linux C开发,就用的这种)。
  • 4.更复杂的应用层协议;
 
作者:orange1438
出处:http://www.cnblogs.com/orange1438/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


UDP主要丢包原因及具体问题分析
 
一、主要丢包原因
 
1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
 
2、发送的包巨大丢包:虽然send方法会帮你做大包切割成小包发送的事情,但包太大也不行。例如超过50K的一个udp包,不切割直接通过send方法发送也会导致这个包丢失。这种情况需要切割成小包再逐个send。
 
3、发送的包较大,超过接受者缓存导致丢包:包超过mtu size数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。
int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
 
4、发送的包频率太快:虽然每个包的大小都小于mtu size 但是频率太快,例如40多个mut size的包连续发送中间不sleep,也有可能导致丢包。这种情况也有时可以通过设置socket接收缓冲解决,但有时解决不了。所以在发送频率过快的时候还是考虑sleep一下吧。
 
5、局域网内不丢包,公网上丢包。这个问题我也是通过切割小包并sleep发送解决的。如果流量太大,这个办法也不灵了。总之udp丢包总是会有的,如果出现了用我的方法解决不了,还有这个几个方法: 要么减小流量,要么换tcp协议传输,要么做丢包重传的工作。
 
 
二、具体问题分析
 
1.发送频率过高导致丢包
 
很多人会不理解发送速度过快为什么会产生丢包,原因就是UDP的SendTo不会造成线程阻塞,也就是说,UDP的SentTo不会像TCP中的SendTo那样,直到数据完全发送才会return回调用函数,它不保证当执行下一条语句时数据是否被发送。(SendTo方法是异步的)这样,如果要发送的数据过多或者过大,那么在缓冲区满的那个瞬间要发送的报文就很有可能被丢失。至于对“过快”的解释,作者这样说:“A few packets a second are not an issue; hundreds or thousands may be an issue.”(一秒钟几个数据包不算什么,但是一秒钟成百上千的数据包就不好办了)。 要解决接收方丢包的问题很简单,首先要保证程序执行后马上开始监听(如果数据包不确定什么时候发过来的话),其次,要在收到一个数据包后最短的时间内重新回到监听状态,其间要尽量避免复杂的操作(比较好的解决办法是使用多线程回调机制)。
 
2.报文过大丢包
 
至于报文过大的问题,可以通过控制报文大小来解决,使得每个报文的长度小于MTU。以太网的MTU通常是1500 bytes,其他一些诸如拨号连接的网络MTU值为1280 bytes,如果使用speaking这样很难得到MTU的网络,那么最好将报文长度控制在1280 bytes以下。
 
3.发送方丢包
 
发送方丢包:内部缓冲区(internal buffers)已满,并且发送速度过快(即发送两个报文之间的间隔过短);  接收方丢包:Socket未开始监听;  虽然UDP的报文长度最大可以达到64 kb,但是当报文过大时,稳定性会大大减弱。这是因为当报文过大时会被分割,使得每个分割块(翻译可能有误差,原文是fragmentation)的长度小于MTU,然后分别发送,并在接收方重新组合(reassemble),但是如果其中一个报文丢失,那么其他已收到的报文都无法返回给程序,也就无法得到完整的数据了。 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/LANGZI7758521/article/details/52789793

智能推荐

php defined or define,define与defined有什么区别-程序员宅基地

文章浏览阅读555次。define与defined的区别有:1、define是用来定义一个常量的且常量被定义后就不能再改变或取消;2、defined是检测常量是否被定义,若存在返回true,不存在返回false。【推荐教程:PHP教程】define与defined的区别definedefine是用来定义一个常量,常量表示的就是全局范围,因此不需要考虑作用域就可以直接在脚本中的任何地方进行访问。但是需要注意的一点是常量一..._php defined('') or define('', ");

【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十一式)_算法独孤九剑-程序员宅基地

文章浏览阅读491次。2022年平安夜,和WeThinkIn的文章更配哦_算法独孤九剑

oracle和mysql使用区别大吗_Oracle和MySQL在使用上的区别-程序员宅基地

文章浏览阅读825次。1、 Oracle是大型数据库而MySQL是中小型数据库,MySQL是开源的而Oracle的价格非常高。2、 Oracle支持大并发,大访问量。3、 安装所用的空间差别也是很大,MySQL安装完后用100多M而Oracle有3G左右,而且使用的时候Oracle占用特别大的内存空间和其他机器性能。4、 在使用上的一些区别:1)、主键:MySQL一般使用自动增长类型,在创建表时,只要指定表的主..._oracle数据库与mysql的操作一样吗

基于51单片机微波炉简易控制仿真设计数码管显示proteus仿真+程序+设计报告+讲解视频)-程序员宅基地

文章浏览阅读823次,点赞23次,收藏13次。基于51单片机微波炉简易控制仿真设计数码管显示( proteus仿真+程序+设计报告+讲解视频)仿真图proteus7.8及以上程序编译器:keil 4/keil 5编程语言:C语言设计编号:S0071。

人脸识别~警察领域-程序员宅基地

文章浏览阅读214次。比如,我一朋友做显著性检测,如果只在实验中通过搭建框架、训练测试,得出结果,那只是看到一个理论的表现,但是我朋友实验室有专门的显著性眼动仪,其可以通过现有模型的辅助,去人为进行实际实验,观察每一幅图像的显著性点及区域(说到这,我们平台准备下期为大家带来显著性检测),所以,本次分享的文献有些乏味,但希望做人脸领域的小伙伴,可以通过实际生活中的一些经验,通过数学的方式应用到模型当中,对实际场景的检测或识别有一定的提升。在没有目标的试验中,参与者可以引起正确的反应(正确的拒绝)或错误地识别错误者的脸(假阳性)。

拉扎维模集笔记-程序员宅基地

文章浏览阅读1.1k次,点赞6次,收藏35次。1.ro是什么答:ro是沟长调制效应的等效电阻,值约为1/(λ*Id)。2.η是什么答:η是体效应的影响3.PVT是什么答:P是工艺影响;V是电压影响;T是温度影响;L是负载影响。_模集

随便推点

【船舶】基于simulnk模拟船舶动力定位-程序员宅基地

文章浏览阅读985次,点赞21次,收藏22次。船舶动力定位(DP)是一种先进的船舶控制系统,能够使船舶在没有任何锚泊或系泊的情况下保持其位置和航向。DP 系统通过使用推进器、舵机和传感器来实现这一目标。DP 系统通常用于需要在海上进行精确操作的船舶,例如钻井船、起重船、铺管船和科学研究船。DP 系统还可以用于在恶劣天气条件下保持船舶的安全,例如在飓风或台风期间。

ThreadX在mdk(AC5)中的移植_threadx移植-程序员宅基地

文章浏览阅读771次。Threadx是由 Express Logic 公司开发的一款实时操作系统(RTOS),2019年被微软收购,成为了微软的一款Azure RTOS。在2020年,ThreadX也加入了开源大军,将ThreadX内核及其各大组件开源免费。ThreadX可以说是一款发展非常迅猛的RTOS,相信最近两年有了解它的朋友都能理解。2019年:被微软收购;2020年:免费开源;2021年:上线中文版手册;Azure RTOS ThreadX 文档。_threadx移植

matlab-m文件常用积分函数-ode45含有时变参数用法/菜鸟理解4_simulink积分器问题-程序员宅基地

文章浏览阅读7.6k次,点赞53次,收藏92次。目录写在前面ode45积分器带有时变参数的ode45积分总结写在后面写在前面本人大四狗一名,最近在帮实验室肝项目,毕设用的强化学习暂且放下了一段时间,所以没有更新。在给实验室打工的过程中,遇到了一个需要用到时变参数的微分方程组,解决这种问题利用simulink很好解决,但是项目要求使用m文件进行编程,在以往的学习中,m文件的积分函数一般就是使用ode45,变步长积分器。常用的语法是[t,y] = ode45(@odefun,tspan,y0)[t,y] = ode45(@odefun,tspan,y_simulink积分器问题

xenser服务器虚拟化,Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)-程序员宅基地

文章浏览阅读465次。《Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)》由会员分享,可在线阅读,更多相关《Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)(3页珍藏版)》请在人人文库网上搜索。1、Citrix 服务器虚拟化之七 Xenserver 虚拟机复制XenServer 包含两种克隆虚拟机的方法,完整复制和快速复制。完整复制就是将虚拟机完整地复制一份,复制速度取决于存储性..._xenserver没有xentools

[STM32WBA]【STM32WBA52CG测评】开箱&呼吸灯-程序员宅基地

文章浏览阅读294次。支持 BLE 5.3 全部功能,比如: long-range,1/2M 传输速率、 LE audio、扩展广播, AOD/AOA,.LE增强版连接更新功能,BLE 以及 802.15.4的私有协议,支持matter相关应用。另外,因为它是基于Cotex-M33核,具有更高的安全性能,支持SESIP-L3, 同时基于新一代ST MCU低功耗平台,具有更优的低功耗性能。本开发板带的外部晶振是32M的。灯最亮的时候高电平时间为0,为了30次将0变成500,每次让duty_num增大500/30,就是17。_stm32wba52

静态网页设计——电影推荐网(HTML+CSS+JavaScript)_电影推荐网页代码-程序员宅基地

文章浏览阅读999次,点赞26次,收藏21次。声明:该文章只是做技术分享,若侵权请联系我删除。!!使用技术:HTML+CSS+JS(静态网页设计)主要内容:对好看的电影进行推荐。该页面使用p标签和人span标签嵌入许多文本,将关于网站主题的介绍全部写到网页中,文字排版根据字数来进行,使用不会出现不协调的情况。在文字旁边,使用img标签嵌入一些图片,使得网页整体更加的美观。_电影推荐网页代码

推荐文章

热门文章

相关标签