说实话,平常写的时候都很少去注意Recv函数返回值的问题…

今天被大坑一波…调了一下午,最终在学长的帮助下解决了。记一下吧。

首先来看这样一句话:

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

来自CSDN… zhao4zhong1 老师…这里就不给链接了…

然后来谈谈Recv函数的返回值吧。

一般情况下, Recv函数的返回值都是接收到的数据长度。

比如这样的:(Win32项目 下的 Debug输出)

其输出结果如下:

这是一段从服务器获取资源后的打印输出…

得出一个结论:一般来说 recv函数都是接受 8192字节…

我去抓个包看看…

首先第一张图。

SYN Seq = 0

SYN ACK Seq = 0 Ack = 1

ACK Seq = 1 ACK = 1

TCP三次握手不解释…

recv-1

然后注意标蓝色的那一行…就是我们的16W数据请求报文…继续看(忽略掉通信心跳,那是维持链接的,不然服务器会主动断开连接…)

recv-2

中间这一部门是我们16W报文的发送和应答…可以发现TCP把报文拆成了一段又一段进行发送,其实这个拆分和重组是在网络层完成的…请注意,是在网络层完成的。

PS…这里我略去了很多没有展出出来

recv-3

好,最后我们看到我们自己的协议了,长度是 161583…

综合上面的 2 – 17次recv 就可以发现了…也恰好是 161583…

(后面是第二次请求,这里也抓出来展示了)

从这里好像可以得出一个结论…一次Recv一般不会超过 8192字节…多于这个的情况也有。(比如第二次和第18次嘛…)

 

其实不是的…我们在recv函数前面加个Sleep来玩玩…

再大一点…( Sleep(2000); )

所以可以发现…其实真的只是数据来慢了…哈哈哈

其实recv函数的作用只是从缓冲区把数据读出来…只是把数据从缓冲区里读出来…只是把接受缓冲区的数据读出来…

重要的事情说三遍…数据的发送和接受都是协议完成的…recv操作和send操作只是把数据从缓冲区读出来或者放到缓冲区里去…

 

好了,讲了很多杂七杂八的东西,那我面临的问题到底是什么呢?

其实就是…

这个函数,有那么一段时间写错了一点,一不小心 iLeftBuffSize 的值小于0了…于是乎报错…

报的还比较奇怪 是 10014…我就一直以为是第二个参数 Buff 的地址越出去了…结果不是。

然后就一直查,问学长,搞出了上面那么多玩意……

真是难..

Socket编程 报错: Recv函数 返回值 -1  LastError 10014

 

这里再转载部分来自网上的…Recv函数返回值的记载吧

如果recv在获取数据时出错,那么它返回SOCKET_ERROR;

如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

默认 socket 是阻塞的 解阻塞与非阻塞recv返回值没有区分,都是

<0 出错

=0 连接关闭

>0 接收到数据大小。

返回值<0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收。

只是阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要循环读取)。

 

最后,失败返回 -1,

errno 被设为以下的某个值 (GetLastError)

EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时

EBADF:sock不是有效的描述词

ECONNREFUSE:远程主机阻绝网络连接

EFAULT:内存空间访问出错

EINTR:操作被信号中断

EINVAL:参数无效

ENOMEM:内存不足

ENOTCONN:与面向连接关联的套接字尚未被连接上

ENOTSOCK:sock索引的不是套接字 当返回值是0时,为正常关闭连接;

 

PS. Win32 要加 WSA  比如 WSAEFAULT

 

【Socket】Recv函数返回值相关小记
Tagged on:
0 0 投票数
Article Rating
订阅评论
提醒

0 评论
内联反馈
查看所有评论