大家遇到过TCP接收数据,字节切片过长丢失字符的问题吗?

DukeAnn · · 1980 次点击
5楼 <a href="/user/BlackBerryX" title="@BlackBerryX">@BlackBerryX</a> tcp除了超时,异常等处理之外,常规数据上要处理的点。&lt;/br&gt; 1.tcp在读取和发送时, 要注意使用的NONBLOCK还是BLOCK的。golang是NONBLOCK的, 所以在read时, 要注意指定读取的字节数。&lt;/br&gt; 比如传入1024大小的slice, 但由于非阻塞, backlog有数据就通知可以读了, 所以可能会在小于1024时就读取了。同样写的时候也要注意实际写入的字节数。&lt;/br&gt; 2.半包是在发送的数据比较多时,tcp会拆分成一个一个小包发送。发送到目标服务器缓存后, 非阻塞时会直接通知程序去读取,阻塞时在缓存满了也会通知程序读取,两者都会导致数据未接收全。 粘包则是小包或者发送方发送速度大于接收方时,缓存区存储了多个消息的内容。程序在未定义包的区分时,就会把不同的包作为同个包来读取。&lt;/br&gt; 短链接时,如果每次直到读完即循环读取直到EOF, 然后再处理是可以解决,只收数据的场景没问题。当要写回响应结果时就不行,因为链接已经关闭。又因为tcp是双全共工,发送方可以只关闭读也是可以的,不过我很少见到这么处理的。&lt;/br&gt; 更加常见的做法是自定封包解包, 最简单的一种是先写4字节长度,然后再写数据。接收时先读4位,然后读数据。 但是这种会存在问题,一旦某个环节读错位了,就可能导致长度不正确,导致该链接一直等待数据读完。一种简单的做法时再包头前加一个魔数,当头几个字节和魔数不匹配,直接关闭链接表示错误。以上只是简单的,实际根据自己的设计,自定义协议。&lt;/br&gt; 还有种简单的是处理字符串时,用特定分隔符做包分割,如换行等。非万能场景。
#6
更多评论
虽然不知道你怎么解决的,做个提醒,你的代码完全没有处理半包粘包。如果是特殊场景, 那当我没说
#2