关于recv接收数据的问题,总是接收buffer大小的数据

yeyumin89 2012-02-07 06:52:45
ACE::recv(handlers, buffer, size),服务端连续不断的发送数据来(数据长度可能不等),每次不等数据接收完后面的数据就会压进来,而recv每次都会copy buffer大小的数据,造成buffer里是上个没收完的数据和这个数据
比如每次发送500个字节,接收buffer为1024,发送5次,按理应该接到的大小是这样:
500
500
500
500
500
但是实际是这样:
1024
1024
452

如果数据大于buffer,比如1030,应该是:
1024
6
1024
6
1024
6
1024
6
1024
6
但是实际会是这样:
1024
1024
1024
1024
1024
30

这是怎么回事啊,是不是要设置什么东西,c里的recv好像也是这样
...全文
939 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2012-02-10
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
我是这样的,大家看下这样好不好。我数据放到包里面,包的大小是4096,每次发送4096,recv buffer也设置成4096,这样每次就能copy一个完整的包下来解包,就不会有之前说的每次可能copy下来不完整的包而需要多个包的数据接到一起
Wolf0403 2012-02-10
  • 打赏
  • 举报
回复
你盯着一个 socket 读不会得到两个 client 的内容。
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 wolf0403 的回复:]

引用 20 楼 yeyumin89 的回复:

引用 18 楼 wolf0403 的回复:

楼主:一定要分包的话,在应用层分。每次发内容之前先发一个表示包大小的数字,客户端就读这么多字节。


这样发两次不太好吧,如果我一个客户端有多个链接的话


TCP 是一个连接一个 socket 的,不存在你说的问题。
[/Quote]
也就是一个链接系统就会分配一个系统的接收缓冲区?
Wolf0403 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 yeyumin89 的回复:]

引用 18 楼 wolf0403 的回复:

楼主:一定要分包的话,在应用层分。每次发内容之前先发一个表示包大小的数字,客户端就读这么多字节。


这样发两次不太好吧,如果我一个客户端有多个链接的话
[/Quote]

TCP 是一个连接一个 socket 的,不存在你说的问题。
赵4老师 2012-02-10
  • 打赏
  • 举报
回复
send容易,recv放缓存再从缓存里面解包难。
AndyZhang 2012-02-10
  • 打赏
  • 举报
回复
握手协议,每次发过去,接受上次的确认再发下一次
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 feng32tc 的回复:]

如果要TCP应用层报文不粘在一起,只能使用应答机制,A发送1030字节,结果分成了1024+6两个报文,然后B收到1030字节后发个ACK,A在收到ACK后再发下一个报文。

不过这样TCP就没有速率上的优势了。

一般的做法就是上面说的缓冲。应用层报文分成两部分,头(Header)和数据。头的长度是固定的,内部包含数据部分的长度。

开始缓冲区的空的,程序不断接受数据,直到已收到的……
[/Quote]
缓冲区中的其它数据向前移动n个字节是什么意思
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 wolf0403 的回复:]

楼主:一定要分包的话,在应用层分。每次发内容之前先发一个表示包大小的数字,客户端就读这么多字节。
[/Quote]

这样发两次不太好吧,如果我一个客户端有多个链接的话
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 zhao4zhong1 的回复:]

引用 16 楼 yeyumin89 的回复:
引用 15 楼 zhao4zhong1 的回复:

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!


之前遇到就是这种情况,我后面把包的大小和send buffer和recv buffer的大小定义一样大,这样每次recv到buffer……
[/Quote]

大家说的分包解包不就是这个意思吗
Wolf0403 2012-02-10
  • 打赏
  • 举报
回复
楼主:一定要分包的话,在应用层分。每次发内容之前先发一个表示包大小的数字,客户端就读这么多字节。
赵4老师 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 yeyumin89 的回复:]
引用 15 楼 zhao4zhong1 的回复:

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!


之前遇到就是这种情况,我后面把包的大小和send buffer和recv buffer的大小定义一样大,这样每次recv到buffer里的数据就是一个完整的包,处理起来方便,不知到这样……
[/Quote]
你试试在大网环境下重复发送接收10万次就知道好不好了。(^_^)
要深刻理解“TCP是面向连接基于流的通讯”这句话啊!
yeyumin89 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 zhao4zhong1 的回复:]

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
[/Quote]

之前遇到就是这种情况,我后面把包的大小和send buffer和recv buffer的大小定义一样大,这样每次recv到buffer里的数据就是一个完整的包,处理起来方便,不知到这样好不好
feng32tc 2012-02-08
  • 打赏
  • 举报
回复
如果要TCP应用层报文不粘在一起,只能使用应答机制,A发送1030字节,结果分成了1024+6两个报文,然后B收到1030字节后发个ACK,A在收到ACK后再发下一个报文。

不过这样TCP就没有速率上的优势了。

一般的做法就是上面说的缓冲。应用层报文分成两部分,头(Header)和数据。头的长度是固定的,内部包含数据部分的长度。

开始缓冲区的空的,程序不断接受数据,直到已收到的字节数超过Header的长度。这时就知道数据部分的长度了,继续接受数据直到第一个应用层报文完全收到。

然后把第一个应用层报文取出来,缓冲区中的其它数据向前移动n个字节(n是头的数据部分的总长度),准备接受下一个应用层报文。
yeyumin89 2012-02-08
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 forever_feng 的回复:]
把socket设置为非阻塞,然后循环recv到一个buffer,然后解析并且移动读指针。
因为一次recv可能收到半个包,1个包,或者1个半甚至多个包。
[/Quote]

buffer里有1个或者多个包都好说,因为是完整的。我就是在想遇到半个或者不全的包怎么解决,我把数据拿出来怎么存啊,数据不完整,其他的数据下次copy到buffer才能拿出来拼到一起解包,这个怎么弄啊
程序员小迷 2012-02-08
  • 打赏
  • 举报
回复
这不就是缓冲机制么
yeyumin89 2012-02-08
  • 打赏
  • 举报
回复
求指点
平凡的思想者 2012-02-08
  • 打赏
  • 举报
回复
把socket设置为非阻塞,然后循环recv到一个buffer,然后解析并且移动读指针。
因为一次recv可能收到半个包,1个包,或者1个半甚至多个包。
yeyumin89 2012-02-08
  • 打赏
  • 举报
回复
能不能发个非阻塞简单的封包解包示例啊
我现在写了个协议,但是接收端遇到一个包被拆分两次copy进buffer,我不知到该怎么处理了
加载更多回复(6)

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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