返回信息流百度一下不就得了
这是一条镜像帖。来源:北邮人论坛 / iwhisper / #7072381同步于 2024/4/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
IWhisper机器人发帖
面试问了个 tcp粘包问题
IWhisper#241
2024/4/18镜像同步14 回复
订阅后,新回复会通过你的通知中心匿名送达。
14 条回复
所谓粘包半包应该是应用层的问题,比如对方调用3次socket.write()发送了3次数据分别有A、B、C个字节,TCP将这些字节送到你的传输层。但是你的传输层向上层应用层传送这些字节也就是你调用socket.read()时,并不能保证产生3次读事件也不能保证3次分别读到A、B、C个字节,有可能只有1次读事件并读到了A+B+C个字节
也就是说TCP只负责可靠地把那A+B+C个字节送到你的传输层,不负责消息边界。TCP眼里所谓3次消息都是一堆字节流,把这堆字节不重不漏不错不乱地送给你的应用层它的任务就完成了,你需要在应用层自行处理消息边界问题。我是这么理解的[em2]
①TCP是面向字节流传输的协议,它把客户端提交的请求数据看作一连串的无结构的字节流,并不知道所传送的字节流的含义,也并不关心有多少数据流入TCP输出缓冲区中。
②每次发多少数据到网络中与当前的网络拥塞情况和服务端返回的TCP窗口的大小有关,涉及TCP的流量控制和阻塞控制,且与Netty的反压有关。如果客户端发送到TCP输出缓冲区的数据块太多,那么TCP
会分割成多次将其传送出去;如果太少,则会等待积累足够多的字节后发送出去。很明显,TCP这种传输机制会产生粘包问题。
③当服务端读取TCP输入缓冲区中的数据时,需要进行拆包处理,并解决粘包和拆包问题,比较常用的方案有以下3种。
·将换行符号或特殊标识符号加入数据包中,如HTTP和FTP等。
·将消息分为head和body,head中包含body长度的字段,一般前面4个字节是body的长度值,用int类型表示,但也有像Dubbo协议那种,head中除body长度外,还有版本号、请求类型、请求id等。
·固定数据包的长度,如固定100个字节,不足补空格。
步骤④~⑥与步骤①~③类似。TCP的这些机制与Netty的编码和解码有很大的关系。Netty采用模板设计模式实现了一套编码和解码架构,高度抽象,底层解决TCP的粘包和拆包问题,对前面介绍的3种方案都做了具体实现。
第1种方案,Netty有解码器LineBasedFrameDecoder,可以判断字节中是否出现了“\n”或“\r\n”。
第2种方案,Netty有编解码器LengthFieldPrepender和 LengthFieldBasedFrameDecoder,可以在消息中加上消息体长度值,这两个编解码器在之前的实战中用到过。
第3种方案,Netty有固定数据包长度的解码器 FixedLengthFrameDecoder。此方案一般用得较少,比较常用的是前两种方案。
简单来讲,tcp粘包就是说,tcp发送的是字节流,但是呢,只发这些没办法区分到哪儿算一条消息,也就相当于消息和消息粘在一起了,这就是粘包问题。
此外,你还得了解了解怎么解决,我记得有三种还是几种方法,你多看看多背背就行