于socket编程的一个难点:recv()函数的返回问题!

fififisher 2011-01-06 10:59:45

在客户端,发送"I love you!",按以下三种办法发送,其中ClientSocket是客户端的套接字描述符:

第一种:
string str("I love you!");
send(CientSocket, str.c_str(), str.size(), 0);


第二种:
string str1("I love");
string str2(" you!");
send(CientSocket, str1.c_str(), str1.size(), 0);
send(CientSocket, str2.c_str(), str2.size(), 0);



第三种:
string str1("I love");
string str2(" you!");
send(CientSocket, str1.c_str(), str1.size(), 0);
sleep(10秒);
send(CientSocket, str2.c_str(), str2.size(), 0);


请问:

服务端的recv()函数,分别返回多少次?

第一种情况,我知道肯定是返回一次。

问题是第二和第三种情况,很难区分。

关键是,我不知道recv()函数返回的条件。即当符合什么条件,recv()函数就会(才会)返回?
...全文
551 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
liutengfeigo 2011-01-08
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zhao4zhong1 的回复:]

请深刻理解TCP/IP是基于流的这一概念。
也就是说,如何发送和如何接收没有关系。
比如一条小溪,上游的水是按滴、按碗、按盆、按缸倒进去跟下游的水流多大和流多快无关。
[/Quote]
精辟
ww884203 2011-01-08
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zhao4zhong1 的回复:]

请深刻理解TCP/IP是基于流的这一概念。
也就是说,如何发送和如何接收没有关系。
比如一条小溪,上游的水是按滴、按碗、按盆、按缸倒进去跟下游的水流多大和流多快无关。
[/Quote]
牛人
arong1234 2011-01-08
  • 打赏
  • 举报
回复
问题是你为什么要问这个问题?实际上连第一种情况,也不保证是一次返回的,正确的实现就应该忽略“到底几次返回”这种细节,老老实实进行报文重组。任何依赖recv会需要几次才能读完的逻辑都是错误的

[Quote=引用 6 楼 fififisher 的回复:]
引用 5 楼 ayw215 的回复:

这样的话recv可能返回很多次。。
你看代码,不是用的while来不停的recv么。。。


所以我就是想知道:返回的条件?
即什么时候,recv才会返回??
[/Quote]
liugang9931706 2011-01-08
  • 打赏
  • 举报
回复
TCP/IP协议是不是根据两个参数:
1、时间间隔,时间到了就返回,不论buf装了多少。
2、缓冲区装满就返回,jitterbuf的大小有关。
现在很多自定的网络协议也是这么定义的。
赵4老师 2011-01-07
  • 打赏
  • 举报
回复
请深刻理解TCP/IP是基于流的这一概念。
也就是说,如何发送和如何接收没有关系。
比如一条小溪,上游的水是按滴、按碗、按盆、按缸倒进去跟下游的水流多大和流多快无关。
管哥的天下 2011-01-07
  • 打赏
  • 举报
回复
recv,会返回接收数据的长度,如果没有数据就返回0
苍蝇①号 2011-01-06
  • 打赏
  • 举报
回复
不定,可能是1次、2次、三次,因为你的数据是在太小了,为了网络性能操作系统会缓存一次发送,当然这有一定的时间限制,如果时间太近了就缓存,淡然要看具体情况了,而且也可以设置socket option
justkk 2011-01-06
  • 打赏
  • 举报
回复
“第一种情况,我知道肯定是返回一次”
这个也不见得吧,很可能因为网络原因,服务端只读取了部分字节

通常服务端应该循环读取,每次判断读取的字节数目,直到读完指定的字节数目,或者客户端关闭连接。
服务端读取过程中,不用关心,也不知道,客户端到底发送了几次。
服务端面对的只是一个socket缓冲区
mcd_23 2011-01-06
  • 打赏
  • 举报
回复
每次调用send,发送内容的前4个字节表示长度,后面+要发送的数据。

接收时,先recv 4个字节,得到长度length
recvbytes=recv(info->client_fd, &length, 4,0))
再接数据
recvbytes=recv(info->client_fd, buf, length,0))
龙哥依旧 2011-01-06
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 fififisher 的回复:]
引用 5 楼 ayw215 的回复:

这样的话recv可能返回很多次。。
你看代码,不是用的while来不停的recv么。。。


所以我就是想知道:返回的条件?
即什么时候,recv才会返回??
[/Quote]
可以设置一次接收的长度和超时时间,不到指定大小不返回!
ayw215 2011-01-06
  • 打赏
  • 举报
回复
很多种情况都会导致recv返回-1的。。
fififisher 2011-01-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ayw215 的回复:]

这样的话recv可能返回很多次。。
你看代码,不是用的while来不停的recv么。。。
[/Quote]

所以我就是想知道:返回的条件?
即什么时候,recv才会返回??
ayw215 2011-01-06
  • 打赏
  • 举报
回复
这样的话recv可能返回很多次。。
你看代码,不是用的while来不停的recv么。。。
[Quote=引用 3 楼 fififisher 的回复:]

对了,忘了提醒:
服务器是这样recv()的:

#define MAXDATASIZE 1000
while((recvbytes=recv(info->client_fd,buf,MAXDATASIZE,0))>0)
[/Quote]
fififisher 2011-01-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ddlddy 的回复:]

收到了就返回,send的多了,有可能一次就recv了,就是所谓的粘包!
[/Quote]


你提到“粘包”这个概念,我还第一次听说。看来,你是专业的!
fififisher 2011-01-06
  • 打赏
  • 举报
回复
对了,忘了提醒:
服务器是这样recv()的:

#define MAXDATASIZE 1000
while((recvbytes=recv(info->client_fd,buf,MAXDATASIZE,0))>0)
bdmh 2011-01-06
  • 打赏
  • 举报
回复
recv,会返回接收数据的长度,如果没有数据就返回0
龙哥依旧 2011-01-06
  • 打赏
  • 举报
回复
收到了就返回,send的多了,有可能一次就recv了,就是所谓的粘包!

64,654

社区成员

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

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