【你问我答】什么是tcp粘包?应该如何解决?

问题描述:

什么是tcp粘包?应该如何解决?

回答有奖:

选取一位认真回答问题的牛友,赠送200牛币!
▶回答尽量有自己的思考,不要单纯的只是复制粘贴定理定义,或者他人blog哦~

你问我答问题汇总:点击进入
关注你问我答栏目:点击关注

你问我答 - 答问题,成大佬,拿牛币!
你问我答是牛客新栏目,每周1期几个面试中真实遇到的问题,
牛友在问题贴下留下自己的知识,经验与见解,
帮助更多牛友了解更多技术相关知识!
#悬赏##Java工程师##面试题目#
全部评论
什么是TCP粘包问题? TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。 造成TCP粘包的原因 (1)发送方原因 TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事: 只有上一个分组得到确认,才会发送下一个分组 收集多个小分组,在一个确认到来时一起发送 Nagle算法造成了发送方可能会出现粘包问题 (2)接收方原因 TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。 什么时候需要处理粘包现象? 如果发送方发送的多组数据本来就是同一块数据的不同部分,比如说一个文件被分成多个部分发送,这时当然不需要处理粘包现象 如果多个分组毫不相干,甚至是并列关系,那么这个时候就一定要处理粘包现象了 如何处理粘包现象? (1)发送方 对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。 (2)接收方 接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。 (2)应用层 应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。 解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢? 格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。 发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。
3 回复 分享
发布于 2020-12-03 08:15
这个问题简单描述就是: A端调用了多次send,B端一个recv就都读出来了 tcp本来就是这么设计的,本来就是基于字节流而不是消息包的协议,数据变成字节流发到对面去,而且保证顺序不会乱,但是不进行字节流解析。 一般有3种解决方案: (1)发送固定长度的消息 (2)把消息的尺寸与消息一块发送 (3)使用特殊标记来区分消息间隔
2 回复 分享
发布于 2020-12-02 00:11
首先TCP是面向流的,所以它发送的消息并不保证一次是一个包的发送。因为有naggle算法,所以会等差不多200ms左右,如果有下一个报文这个时候发送的话,会一起发出去。所以会造成粘包。 1、有用分隔符表示一个包的。比如\r\nxxxxxx\r\n这就其中xxxxx就是一个包的内容。 2、用带长度的报文格式,比如LV, L固定字节,表示后面V的长度。 3、用固定包大小,不足的补。
点赞 回复 分享
发布于 2020-12-03 17:17
1 特定结束符比如\r\n 参考http 2 约定协议字段,类型,长度,校验,加密,参考websocket
点赞 回复 分享
发布于 2020-12-02 00:19

相关推荐

11-17 01:10
门头沟学院 Java
1.项目介绍2.看你做过支付,你怎么确保账单和资金流水对得上?具体怎么设计对账系统3.jvm知道吧,对象在堆上分配内存时,MarkWord里都存了哪些标志位?为什么在偏向锁状态下对象头会变化4. 那如果一个对象正在偏向锁状态,被别的线程抢了,会经历哪些锁升级过程?5. 你能画出从偏向锁 → 轻量级锁 → 重量级锁这整个过程的结构图吗?每一步触发条件是什么6.GC时stw到底是谁发起的7. 你知道SafePoint吗?为什么线程必须在SafePoint 才能安全停下8.你觉得对象分配为什么需要TLAB9.如果我告诉你一个接口平均延迟是30ms,但99分位延迟是900ms,你能从GC的角度分析可能的原因吗13.MySQL熟悉么,如果两个事务,一个更新,一个查询,说一下它们在 RC和 RR下的可见性14.说一下MySQL事务的隔离级别有哪些15. 你在项目里用 Redis 的 zset 做延时任务,那我问你:如果Redis挂了,你的任务是不是全没了?怎么做容灾16.如果Redis 里的延时任务量非常大(上百万),你每次都扫一遍?17.你提到用LRU淘汰策略,那你知道 Redis 的 LRU 是精确的吗18. 看你项目里有用分布式锁,你知道Redisson的Watchdog是怎么续期的?19.如果 Redis 掉线了,锁自动失效了,任务没执行完,怎么办20.redisson分布式锁是不是绝对安全的?它可能出什么问题?21. 我现在有一段多线程的代码,我要去一个主线程去启动3个子线程去执行100个任务,由这个子线程去执行100个任务,然后我主线程它是肯定是要等这100个任务执行完它才会继续往下面走,你要怎么去实现这个逻辑22. 假如有一个接口,里面有ab两个方法,这个接口有两个实现类,那么这个时候我a方法是做一种逻辑,b方法可能做多种业务逻辑,怎么样才能让这种情况更解耦22.手撕:给一个链表,求出每个节点后面下一个大于它的值,如果没有则为0(要求:时间复杂度O(n);不能翻转链表23. 那如果是求每个节点后面最大的值呢?
点赞 评论 收藏
分享
好久没写牛客了,最近我想分享一下我关于技术上的某些看法,我的目的是满足分享欲和给大家一些不一样的观点。凡事都有两面性,技术方案也是一样,很少有一劳永逸的最优解决方案。我这里的中庸之道就是折中的意思。我喜欢举例子来说明观点。从前端常谈的性能优化入手。前端在打包文件的时候有一个分包的概念。目的是为了让单个资源不这么大,导致加载耗时过长,影响用户体验。如何看某个界面的性能的收益呢,当然就有一些指标,比如秒开率,但是核心还是用户的付费意愿和营收指标之类的。分包太大加载时间长影响用户体验,太小又会导致资源请求次数过多,增加在网络过程中耗时,那就要折中。如果就是要得到一个比较好的阈值呢,怎么做。微调。事实上很多这类问题的方案就是开不同的实验组,比较最终不同的收益。哪个收益大就用哪个。再比如react的性能优化手段。会有usecallback之类的缓存手段。但是很少有人谈这类缓存的性能开销。无论是什么缓存方式,都要增加一个是否要缓存的比较过程和缓存内容本身的开销。所以是否要缓存也应该是一个要折中的方案。我说的这些是觉得很多问题大家最好不要片面的看。不只是技术问题,生活上的很多问题,用这种方式表达自己的看法和观点。很多问题都有一个比较好的解决方案,也让别人觉得你成熟可靠。
现在前端的就业环境真的很...
点赞 评论 收藏
分享
评论
点赞
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务