TCP粘包现象 - hustxyj的专栏 - CSDN博客

来源:百度文库 编辑:神马文学网 时间:2024/04/27 23:57:27
首页 资讯 空间 学生 论坛 博客 下载 读书 网摘 程序员 外包 书店 网址 CTO俱乐部 乐知教育 D9区
hustxyj的专栏
条新通知 登录 注册 欢迎 jijo2005! 退出 我的博客 配置 写文章 文章管理 博客首页   全站 当前博客  空间 博客 好友 相册 留言 用户操作
[留言]  [发消息]  [加为好友] 
ID:hustxyj共16次访问,排名2万外,好友0人,关注者0人。
的文章
原创 2 篇
翻译 0 篇
转载 0 篇
评论 0 篇
订阅我的博客
    
 
 
 
[编辑]hustxyj的公告
[编辑]文章分类
学习心得
存档
2010年03月(2)
  TCP粘包现象 收藏
我在暑假做课设的时候要做一个文件传输的功能,于是我有如下设计:
 
发送端A:
char szbuf[MAX_LEN]; while (1)
{
/* 将前1个字节作为消息的标志位(标志该包是否是文件的结尾) */
/* 将文件读入(szbuf+1) */
send(....);
}
       
接收端B:
char szbuf[MAX_LEN]; while (1)
{
recv(....);
/* 将收到的数据写入文件 */
if(/* 标志位说明是文件结尾 */)
{
/* 关闭文件 */
}
}
 
假设我们有一个文本文件,内容都是a
那么按我们的预期一个包的内容应该是1aaaaaaaaaa(假设0表示文件结尾,1表示文件内容,每次发送10个字节的文件内容)
但是有的时候在接收端会读到第一个字节为a的情况,导致判断的时候逻辑出错。为什么呢?
 
上网查了以后,得到以下结论:
由于TCP在发送包的时候是基于流式的,所以会出现以下几种情况:
 
1.假设发送端连续发送两个1aaaaaaaaaa包,那么在接收端的缓冲区中会连续存储着1aaaaaaaaaa1aaaaaaaaaa接收端先后两次按照预期的从缓冲区中读出11个字节,得到1aaaaaaaaaa。
 
2.发送端在发送一个1aaaaaaaaaa的包时,可能会是分两次发送的,也就是说可能第一次只发送了1aaaaa的数据,而第二次将剩下的5个a与第二个包并为aaaaa1aaaaaaaaaa然后再发送。由于TCP基于流式的性质,那么以上发送的1aaaaa和aaaaa1aaaaaaaaaa会被先后写入接收端的缓冲区,合并成1aaaaaaaaaa1aaaaaaaaaa。然后接收端先后两次按照预期的从缓冲区中读出11个字节1aaaaaaaaaa。
 
以上说的是理想情况下的发送与接收,实际情况下,可能会出现第3种情况:
发送端在发送一个1aaaaaaaaaa的包时,分两次发送的,第一次发送了1aaaaa的数据。正当此时,接收端去读缓冲区的时候发现缓冲区中只有6个字节的数据,那么接收端就会只读6个字节上来。那么在下一个包aaaaa1aaaaaaaaaa到达后,接收端如果还是读11个字节的话就会得到aaaaa1aaaaa的结果。也就是我们之前遇到的问题。
 
那么有什么方法可以解决我们这个问题呢?
 
我总结的有两个:
1.既然是文件发送,整个文件是连续的,那么我在发送的时候不需要标志位,接受端不论每次收到几个字节都一股脑地写入文件,在发送完成的时候,由发送端closesocket就可以。
这样实现确实是可以做到不发生错误,但是有一个问题,如果我在发送TCP包的时候确实需要一些标志状态的标志位呢?我在网上找到了另一种方法
2.每次在接收端接受的时候判断收到的字节是否为预期的大小,如果不是,那么再次recv剩下的大小,直到接收端收到预期的大小为止。这样就可以保证每次发送端发出了什么信息,接收端也能收到同样的信息。
 
看了以上的解释后,我再分享一个问题:
我在使用我最初的设计(也就是最前面的那两段会出错的伪码)写出代码后,在两台机子上测试,一台是我家里7、8年前买的老古董电脑,一台是我现在用的本本,此时会有一个神奇的情况,如果是我家的老电脑向我的本本发的时候,会出现逻辑混乱,挂了……然而要是用我的本本向老电脑发文件的时候,却一点问题没有~为什么呢~~?(大家先想一下再看下我的想法)













我的想法是这样的:如果是本本向老电脑发时,由于send速度快些,老电脑recv慢些,所以recv的时候缓冲区中都是充裕的,不会出现那种读不全的情况;而老电脑向本本发的时候,由于send慢,recv快,所以可能在本本recv的时候,老电脑还没send完,这样就会出现前面说的第3中情况。(个人见解,如果异议,敬候……)
发表于 @ 2010年03月20日 10:56:00 | 评论( 0 ) | 编辑| 举报| 收藏 旧一篇:小议内存
查看最新精华文章 请访问博客首页相关文章 发表评论 表 情:           评论内容:  用 户 名: 登录 注册 匿名评论 jijo2005验 证 码:   重新获得验证码     公司简介|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
 Email:webmaster@csdn.net
Copyright © 1999-2010, CSDN.NET, All Rights Reserved  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hustxyj/archive/2010/03/20/5398770.aspx