[问zhao4zhong1]:关于刚才一个TCP问题

DontKissBossAss 2010-06-28 02:03:39
zhao4zhong1大人回答如下

永远不要指望send(什么什么),就recv(什么什么)!
因为send(什么什么),recv(什)recv(么什)recv(么)是很正常的现象。
所以send必须打包,recv必须缓冲和拆包。

tcp是基于流的吧,然后我理解您提出的解决方案是针对异步模式的解决方案

我理解如下:
自己个构造一个简单的帧协议使得包包含如下信息

1:先后顺序
2:内容长度
3:内容

recv 收到以后解包能获取里面的内容。

但是还是有点不明白,比如我发一个完整帧,recv可能收到的不完整么?(假设我这帧就20字节)
。如果不完整 recv 就没办法识别了吧

求解惑
...全文
84 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jinhao 2010-06-29
  • 打赏
  • 举报
回复

//先接收前4个字节
size = 4
while(size < 4)
size += recv(buf + size, 4 - size);

//然后接受剩余的帧数据
size = 0;
data_size = *buf - 4;
while(size < data_size)
size += recv(buf + size, data_size - size);

Jinhao 2010-06-29
  • 打赏
  • 举报
回复
先后顺序可以不用在意

比如前四个字节是表明帧的长度,这一帧后面的内容就是 帧长度-4个字节

在recv的时候.


//先接收前4个字节
size = 4
while(size < 4)
size += recv(buf, 4 - size);

//然后接受剩余的帧数据
size = 0;
data_size = *buf - 4;
while(size < data_size)
size += recv(buf, data_size - size);


顺序是肯定不用担心的.只是recv的,极有可能是一点一点地接收到.因此要自己判断接收到的长度
赵4老师 2010-06-29
  • 打赏
  • 举报
回复
我的思路是将要发送的二进制数据编码,比如base64或hexstr,然后用一个编码中不出现的字节比如0x00作数据间隔,举例:
要发送0x00 0x12 0xef三个字节和0xa0一个字节,hexstr编码后为
"0012ef"

"a0"
即0x30 0x30 0x31 0x32 0x65 0x66六个字节加数据间隔字节0x00调用send

即0x61 0x30两个字节加数据间隔字节0x00调用send

recv(0x30,0x30,0x31,0x32,0x65)缓存
recv(0x66,0x00,0x61)缓存并因为收到0x00返回拆包(0x30,0x30,0x31,0x32,0x65,0x66)的hexstr解码0x00 0x12 0xef三个字节给上层
recv(0x30,0x00)因为收到0x00返回拆包(0x61,0x30)的hexstr解码0xa0一个字节给上层

我想楼主应该明白我的意思了。
相比上面帖子的方法,缺点是发送的数据字节数翻番,优点是不受长度限制,不受长度字节接受不全限制,很少发生数据错位,即使错位,也很容易在下一组数据到来时重新同步。
DontKissBossAss 2010-06-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lvshaoqing 的回复:]

给你个最简单的办法。 包中头字节代表包的长度。 即如果手动包的长度为127,则你收到128个字节后,算取得一个包。 接着去下个包。 如此循环。 一般如果两端都是这么约定的话,不会出错。
[/Quote]

那你这个就是 “send(什么什么),就recv(什么什么)!”
lvshaoqing 2010-06-28
  • 打赏
  • 举报
回复
给你个最简单的办法。 包中头字节代表包的长度。 即如果手动包的长度为127,则你收到128个字节后,算取得一个包。 接着去下个包。 如此循环。 一般如果两端都是这么约定的话,不会出错。
DontKissBossAss 2010-06-28
  • 打赏
  • 举报
回复
UP1

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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