请教:关于TCP接收乱序问题

qjbandy 2007-08-29 07:48:30
在学习socket过程中,近日遇到一个很头疼的问题,苦想了两天还是没有什么头绪。
在使用TCP协议时,接收端收到的数据发生了乱序想象。
TCP定义: 作为一个面向连接的传输层协议,TCP的目标是为用户提供可靠的端到端连接,保证信息有序无误的传输。它除了提供基本的数据传输功能外,还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号,并请求接收方回传确认信息(ack)。发送方如果在规定的时间内没有收到数据确认,就重传该数据。数据编号使接收方能够处理数据的失序和重复问题。数据误码问题通过在每个传输的数据段中增加校验和予以解决,接收方在接收到数据后检查校验和,若校验和有误,则丢弃该有误码的数据段,并要求发送方重传。流量控制也是保证可靠性的一个重要措施,若无流控,可能会因接收缓冲区溢出而丢失大量数据,导致许多重传,造成网络拥塞恶性循环。TCP采用可变窗口进行流量控制,由接收方控制发送方发送的数据量。
因此TCP连接应该保证,所接收的数据先来先到,并有序排列。这情况在写文件时得到了验证,但在内存中却出现了乱序想象。
这是两者的对比:
写入文本的数据:
<Msg><memoid>2402</memoid><title>ddd</title><text>ddd</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:22</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2403</memoid><title>ddd</title><text>ddd</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:25</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2405</memoid><title>f</title><text>f</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:30</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2593</memoid><title>ss</title><text>ss</text><hdate>2007-08-24 11:34:00</hdate><operdate>2007-08-24 11:33:54</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2594</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:01</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2596</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:07</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2597</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:10</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2601</memoid><title>ggddddddddddddddddddd</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 15:12:47</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2602</memoid><title>12</title><text>fddfg</text><hdate>2007-08-30 15:38:42</hdate><operdate>2007-08-24 15:39:15</operdate><end>AHEAD</end></Msg>
<Msg><end>END</end></Msg>


存放于内存的数据:
<Msg><memoid>2402</memoid><title>ddd</title><text>ddd</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:22</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2403</memoid><title>ddd</title><text>ddd</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:25</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2405</memoid><title>f</title><text>f</text><hdate>2007-08-25 15:00:16</hdate><operdate>2007-08-23 15:00:30</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2593</memoid><title>ss</title><text>ss</text><hdate>2007-08-24 11:34:00</hdate><operdate>2007-08-24 11:33:54</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2594</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:01</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2596</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:07</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2597</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:10</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2601</memoid><title>ggddddddddddddddddddd</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 15:12:47</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2602</memoid><title>12</title><text>fddfg</text><hdate>2007-08-30 15:38:42</hdate><operdate>2007-08-24 15:39:15</operdate><end>AHEAD</end></Msg>
<Msg><end>EN2007-08-23 15:00:30</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2593</memoid><title>ss</title><text>ss</text><hdate>2007-08-24 11:34:00</hdate><operdate>2007-08-24 11:33:54</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2594</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:01</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2596</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</hdate><operdate>2007-08-24 11:48:07</operdate><end>AHEAD</end></Msg>
<Msg><memoid>2597</memoid><title>gg</title><text>gg</text><hdate>2007-08-25 11:43:38</D</end></Msg>


实现的代码:
while(true)
{
leng = m_pSocket->Receive(chrBuff, 1024);
file.Seek(0, CFile::end);
file.Write(chrBuff, leng);//写文本
strbuff += chrBuff; //内存存放
}
//判断结束及回收部分省略

很明显ID 为2593~2597的数据发生了重传,写入文本的部分遵循排序,而内存数据发生乱序。
望高手解答。!!!!!!!
...全文
2440 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
JackPan 2012-03-20
  • 打赏
  • 举报
回复
不会乱的,如果乱了,tcp的接收端就把他丢了,让发送端重发(这个是通过超时实现的,具体可以查资料)
dd_zhouqian 2012-01-13
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lifu120 的回复:]

同求
引用 10 楼 et214721856 的回复:
引用 3 楼 unsigned 的回复:
另外按这种接收不会产生乱序,除非同一个Socket上面有两个线程在同时发送或接收。

同个SOKCET,两个线程,一个发送,一个接收,这样就会乱序么?求解。
[/Quote]
不会
lifu120 2011-05-05
  • 打赏
  • 举报
回复
同求
[Quote=引用 10 楼 et214721856 的回复:]
引用 3 楼 unsigned 的回复:
另外按这种接收不会产生乱序,除非同一个Socket上面有两个线程在同时发送或接收。

同个SOKCET,两个线程,一个发送,一个接收,这样就会乱序么?求解。
[/Quote]
周晓荣 2011-05-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 unsigned 的回复:]
另外按这种接收不会产生乱序,除非同一个Socket上面有两个线程在同时发送或接收。
[/Quote]
同个SOKCET,两个线程,一个发送,一个接收,这样就会乱序么?求解。
longge520 2007-09-01
  • 打赏
  • 举报
回复
strbuff += chrBuff; //内存存放
这行估计有0结束符的问题,
rainfull 2007-08-30
  • 打赏
  • 举报
回复
我上次也遇到了类似的问题,主要是没有判断leng是否为零,如果为零,表示结束。
ouyh12345 2007-08-30
  • 打赏
  • 举报
回复
tcp是保证次序的。
问题出现在接受到数据包后,怎样处理的
ddddfbb 2007-08-30
  • 打赏
  • 举报
回复
ft
你怎么判断是重传的?
qjbandy 2007-08-30
  • 打赏
  • 举报
回复
接收完成 以及别的判断部分代码省略了。
我也认为 TCP不可能出现这种情况,但是在这次开发中确实遇到了这个问题。
当有部分数据重传后,我将接收到的数据放入不同地方,没有经过别的处理。出现了 以上两种内容的情况。我做了一个逆序的解析器用来接收<Msg><end>END</end></Msg>这个结束标志。
一旦出现上面所述情况所得的内存数据将不是我们所要的数据。
qjbandy 2007-08-30
  • 打赏
  • 举报
回复
我的疑问在于 接收到的数据流在交给我们的时候发生了乱顺,而不是象TCP的说明那样保证接收到有序的数据。
我这个不是用来传文件的,而是在解析一个快频率,每次数据较小的数据。我不能在这次传输的时候就断开连接。也不可能出现接收到的长度为0的情况。和楼上所说的不是同一个问题。
还有一个,ouyh12345所说的接收到的数据包我没有经过处理,直接让接收到的数据放入两种不同的介质里。
僵哥 2007-08-29
  • 打赏
  • 举报
回复
另外按这种接收不会产生乱序,除非同一个Socket上面有两个线程在同时发送或接收。
僵哥 2007-08-29
  • 打赏
  • 举报
回复
leng没有加判断,当leng=0表示socket断开,leng=-1表示错误发生。
q44072429 2007-08-29
  • 打赏
  • 举报
回复
不可能 单线程 TCP 不会 乱,协议就是这么定的

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧