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
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
TCP粘包现象 - hustxyj的专栏 - CSDN博客
tcp rst packet - tianqio的专栏 - CSDN博客
baozhengw的专栏 - CSDN博客
解决TCP网络传输“粘包”问题 - 志良的技术博客 - 博客园
AGPS简介 - kv110的专栏 - CSDN博客
OpenMAX简介 - shenbin1430的专栏 - CSDN博客
Android flinger - simmer_ken的专栏 - CSDN博客
windows 命令 - orangeman1982112的专栏 - CSDN博客
JNDI概述 - tanghongru1983的专栏 - CSDN博客
指针 - syhhl007的专栏 - CSDN博客
变量命名 - yszwn的专栏 - CSDN博客
什么是PLL - JasonCao的专栏 - CSDN博客
VC积累 - cherryt的专栏 - CSDN博客
fms技术 - wanglilin2000的专栏 - CSDN博客
关于numeric_limits - qianlong88的专栏 - CSDN博客
gcc - sportmanmanman44的专栏 - CSDN博客
TCP包的校验和
STL之vector的使用 - wxdvc的专栏 - CSDN博客
一些实用的TAB效果 - colourbear的专栏 - CSDN博客
气质的养成 - Adi_liu的专栏 - CSDN博客
Android的源代码结构 - 常青的专栏 - CSDN博客
使用自己的make menuconfig - Hermit的专栏 - CSDN博客
系统架构师的修炼 - welcomejzh的专栏 - CSDN博客
ffmpeg与ffdshow的关系 - zysee的专栏 - CSDN博客