2025年Linux网络编程:recv的返回值

Linux网络编程:recv的返回值recv 是网络编程中用于 TCP 传输接收数据的接口 由于工作中一直没有接触到网络编程 虽然知道这个函数 但是没有使用经验 所有对接口细节不是很了解 直到前阵子在项目中调试第三方的源码时 跟踪到这个函数 才发现它的返回值和我想象的不太一样 recv 函数的原型 ssize t

大家好,我是讯享网,很高兴认识大家。

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 1024 int 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 1024 int 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 backoff int 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; } 

这里写图片描述

小讯
上一篇 2025-01-28 23:02
下一篇 2025-03-23 16:12

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/20824.html