日期:2014-05-16  浏览次数:20943 次

关于TCP收发包问题
各位大虾,我有一个很急的问题请教

问题描述:
先建立tcp连接,客户端循环调用send函数发送数据包,就假设循环两次吧。
服务端调用read一直读客户端发来的数据,结果问题来了,接收到的数据有点问题。
通过tcpdump工具抓包分析,发现有时tcp会将两次send的数据一次打包发过去,而有时则是正常一次一次打包发送,后来我想,是不是发送数据太快,于是在每次send后让其睡眠1秒,通过这种方式,发送数据正常了。

问:
tcp会整合调用多次send的数据一次发送 是否属于tcp正常行为?还是我写的程序有问题?
在线等 谢谢!
------解决方案--------------------
tcp是流,只保证顺序到达,但如何打包到达不保证。
例如:发送端三次分别发送123 456 789
接收端可能会任何组合接收,但接收的顺序一定是123456789,可能是1到9次不等。
------解决方案--------------------
这不是典型的基于TCP自定义协议的解析么,必须要考虑的问题:
1、会话管理
2、粘包处理
3、协议解析

每一个链接包装成一个会话,每个会话关联一个数据缓冲,存放接收到的数据,解码器读取缓冲中的数据,将满足自定义协议包长度的bytes读取出来,抛给解析器处理,最后是业务逻辑解析。

简单说,添加一个接收缓冲,就能解决粘包问题。
------解决方案--------------------
做过tcp传输的,没有不知道这个粘包问题的。

最常见的解决办法是把消息包处理成如下格式:

消息类型+消息头部+消息体长度。其中消息类型和消息头部固定字节数。

这样可以适应任何长度的数据包传输。

发送和接收端需要根据这样的格式进行解码
------解决方案--------------------
包头+长度+内容, 
包头的目的就是为了在接收端缓存里面作为切割两个数据包的分界线。比如你随便来个"ABC", 包头定义的越长,切割的错误率越低(主要是内容中也包含和包头同样的字符), 但是信道占用越大.