recv是网络编程中用于TCP传输接收数据的接口,由于工作中一直没有接触到网络编程,虽然知道这个函数,但是没有使用经验,所有对接口细节不是很了解。

直到前阵子在项目中调试第三方的源码时,跟踪到这个函数,才发现它的返回值和我想象的不太一样。

recv函数的原型:

ssize_t recv(int sockfd, void* buf, size_t len, int flags);

之前知道的是如果读取成功,会返回实际读取到的字节数,但是如果读取不到数据呢?一直想当然的认为会返回0,其实并不是,当读取不到数据的时候,返回的是-1,错误码是11,对应的含义是:Resource temporarily unavailable,这里的资源自然是指要读取的数据,因为没有数据可以读取,所以资源不可用。

那么返回值为0表示什么意思?答案是当对端关闭了socket的时候(是真正地关闭,会引发四次握手,而不是减少引用),我们再去调用recv读取数据,会返回0。

下面是测试代码,连接建立后,服务端会网socket发送数据,每次发送后sleep5秒,当发送四次数据后,关闭socket。为了测试在没有数据可读的情况下调用recv的返回值,我们在客户端把socket设置为非阻塞模式,当服务端在sleep时,socket没有数据可读,调用recv后会返回-1,打印出来的错误码是11,当服务端关闭了socket后,再次调用recv则返回0。

服务端代码:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <netdb.h>using namespace std;#define MAX_OF_LISTEN_QUEUE 10
#define MAXBUF 1024int main(){int sockFd;int destSockFd;struct sockaddr_in source;struct sockaddr_in dest;char buff[MAXBUF+1];memset(&source, 0, sizeof(source));source.sin_family = AF_INET;source.sin_port = htons(8235);source.sin_addr.s_addr = inet_addr("192.168.1.109");sockFd = socket(AF_INET, SOCK_STREAM, 0);if(sockFd < 0){cout << "created server socket error!" << endl; }if(bind(sockFd, (struct sockaddr*)&source, sizeof(source)) != 0){cout << "server bind error!" << endl;   }if(listen(sockFd, MAX_OF_LISTEN_QUEUE) != 0){cout << "server listen error!" << endl;}socklen_t len = sizeof(dest);   while(1){destSockFd = accept(sockFd, (struct sockaddr*)&dest, &len);if(destSockFd == -1){cout << "server accept error!" << endl;}else{cout << "server accept a connection!" << endl;break;  }}int hasSend;strcpy(buff, "This message from server!");int count = 0;while(1){count++;if(count > 4)break;sleep(5);cout << "server sending message!" << endl;hasSend = send(destSockFd, buff, strlen(buff), 0); if(hasSend == -1){cout << "server send message error!" << endl;       }if(hasSend == strlen(buff)){cout << "server send OK!" << endl;      }else{cout << "server only send " << hasSend << "bytes!" << endl;     }}   close(destSockFd);  cout << "server will exit!" << endl;
}

客户端代码:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <netdb.h>
#include <sys/select.h>
#include <fcntl.h>using namespace std;#define MAXSLEEP 128
#define MAXBUF 1024int main(){int sockFd;struct sockaddr_in dest;struct sockaddr_in source;char buff[MAXBUF+1];sockFd = socket(AF_INET, SOCK_STREAM, 0);if(sockFd < 0){cout << "created client socket error!" << endl; }memset(&dest, 0, sizeof(dest));dest.sin_family = AF_INET;dest.sin_port = htons(8235);dest.sin_addr.s_addr = inet_addr("192.168.1.109");memset(&source, 0, sizeof(source));source.sin_family = AF_INET;source.sin_port = htons(8234);source.sin_addr.s_addr = inet_addr("192.168.1.109");if(bind(sockFd, (struct sockaddr*)&source, sizeof(source)) != 0){cout << "client bind error!" << endl;   }//use exponential backoffint nsec;for(nsec = 1; nsec <= MAXSLEEP; nsec <<= 1){if(connect(sockFd, (struct sockaddr*)&dest, sizeof(dest)) == 0){cout << "connect to server successfully, will break" << endl;break;  }if(nsec <= MAXSLEEP/2){cout << "connect to server error, will sleep " << nsec << "seconds!" << endl;sleep(nsec);        }}int flag = fcntl(sockFd, F_GETFL, 0);flag |= O_NONBLOCK;fcntl(sockFd, F_SETFL, flag);int recvLen;//setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));while(1){cout << "client recving message!" << endl;recvLen = recv(sockFd, buff, MAXBUF, 0);if(recvLen == -1){cout << "client recv message error!" << endl;if(errno == 11)     cout << "no data to read!" << endl;}else if(recvLen == 0){cout << "server has close!" << endl;break;  }else{buff[25] = '';cout << "client recv " << recvLen << " bytes, message is:" << buff << endl;     }sleep(2);}close(sockFd);cout << "client will exit!" << endl;
}

Linux网络编程:recv的返回值相关推荐

  1. Linux多线程编程-线程函数返回值(返回简单数据类型)

    引言 通过几个实验练习,学习线程之间连接的具体实现.下面列举了两个例子,一个是子线程返回简单数据类型:另一个是子线程返回复杂数据类型. 实现代码 子线程返回简单的数据类型 #include<st ...

  2. 网络编程_bind函数返回值

    #define  _WINSOCK_DEPRECATED_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include&l ...

  3. 【Linux网络编程】并发服务器之多线程模型

    00. 目录 文章目录 00. 目录 01. 概述 02. 多线程服务器 03. 多线程服务器实现思路 04. 多线程服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的协议来分有 ...

  4. 【Linux网络编程】TCP网络编程中connect listen和accept三者之间的关系

    00. 目录 文章目录 00. 目录 01. TCP服务端和客户端流程 02. connect函数 03. listen函数 04. 三次握手 05. accept函数 06. 附录 01. TCP服 ...

  5. 【Linux网络编程】TCP编程

    00. 目录 文章目录 00. 目录 01. TCP概述 02. TCP特点 03. TCP中CS架构 04. TCP相关函数 05. TCP服务端示例 06. TCP客户端示例 07. 附录 01. ...

  6. 【Linux网络编程】组播

    00. 目录 文章目录 00. 目录 01. 组播概述 02. 组播应用分类 03. 组播地址 04. 组播地址与 MAC 地址的关系 05. 套接字选项 06. 程序示例 07. 附录 01. 组播 ...

  7. Linux网络编程 | 定时事件 :Linux常见定时方法、定时器链表、空闲断开

    文章目录 Linux定时方法 定时器链表 空闲断开 Linux定时方法 Linux中为我们提供了三种定时方法,分别是Socket超时选项,SIGALRM信号,I/O复用超时参数.下面一一对其进行介绍. ...

  8. Linux网络编程——黑马程序员笔记

    01P-复习-Linux网络编程 02P-信号量生产者复习 03P-协议 协议: 一组规则. 04P-7层模型和4层模型及代表协议 分层模型结构: OSI七层模型: 物.数.网.传.会.表.应TCP/ ...

  9. Linux网络编程---I/O复用模型之epoll

    https://blog.csdn.net/men_wen/article/details/53456474 Linux网络编程-I/O复用模型之epoll 1. epoll模型简介 epoll是Li ...

最新文章

  1. 《树莓派Python编程入门与实战》——3.5 关于Python交互式shell
  2. Shell编程(week4_day1)--技术流ken
  3. 2017年深度学习优化算法最新进展:改进SGD和Adam方法
  4. INVALID_HANDLE_VALUE的意思和用法
  5. C/C++中使用函数memset对int型数组赋值(0,-1,max,min)
  6. python已经取代了excel_Python已经取代Excel?网友:笑了
  7. 网络(6)-TCP/IP对拥塞控制、滑动窗口如何实现可靠性?
  8. 陆奇技术入局拼多多,拼多多能否摆脱“五环外”?
  9. Coursera, Big Data 3, Integration and Processing (week 1/2/3)
  10. 手机弹奏计算机音乐的软件,APP推荐:11款简单好用工具的APP,一定要懂!
  11. 去了一趟字节跳动,被怼了!
  12. Java多重选择switch
  13. 深度学习论文-Cyclical Learning Rates for Training Neural Networks
  14. 为了研究而玩:游戏分析的方法
  15. swoole 连接mysql_swoole教程:用swoole4操作mysql连接池之读写分离
  16. 【IoT】 产品设计:结构设计之PCB设计(三)
  17. 更多丰富内容,请转移至博主的个人博客——SeaDream乄造梦
  18. C++-鼠标操作大全
  19. 从0开始学Unity做SLG系列(GameFramework框架)
  20. 在Windows中安装MinGW-w64最新版本(目前12.1.0)

热门文章

  1. C/C++常用关键字详解
  2. MindSpore笔记:训练手写数字识别
  3. python turtle什么意思_python turtle 简介
  4. HMAC原理及SM3-HMAC实现
  5. 云计算疑难杂症解决方案一
  6. Unity3D教程之Light光源
  7. 创意前沿:30个别具创意的科技广告欣赏
  8. 系统管理-第6部分——补丁(patch)管理和在线更新
  9. sersync-实时同步服务
  10. FFmpeg video filter FATE测试过程介绍