在Linux中,recv
函数用于从套接字接收数据。当设置为非阻塞模式时,recv
函数会立即返回,而不管是否有数据可读。
基础概念:
recv
)不会等待数据就绪。如果没有数据可读,函数会立即返回一个错误(通常是EAGAIN
或EWOULDBLOCK
),而不是阻塞等待。相关优势:
类型:
recv
总是立即返回,不考虑是否有数据。recv
在指定时间内等待数据,如果超时则返回。应用场景:
select
、poll
或epoll
等多路复用系统调用。遇到的问题及原因:
recv
立即返回EAGAIN
或EWOULDBLOCK
:这通常意味着当前没有数据可读。可能的原因包括:发送方尚未发送数据、网络延迟、或者接收缓冲区已满(对于发送方来说)。解决方法:
select
、poll
或epoll
等系统调用,可以同时监视多个套接字,并在有数据可读时得到通知。recv
返回EAGAIN
或EWOULDBLOCK
。EAGAIN
和EWOULDBLOCK
错误,确保程序不会因此崩溃或进入无限循环。示例代码(使用epoll
和recv
的非阻塞模式):
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
// ... 其他代码 ...
int set_nonblocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) return -1;
flags |= O_NONBLOCK;
return fcntl(fd, F_SETFL, flags);
}
int main() {
int sockfd = ...; // 创建并连接套接字
set_nonblocking(sockfd);
int epollfd = epoll_create1(0);
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = sockfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
while (1) {
struct epoll_event events[10];
int n = epoll_wait(epollfd, events, 10, -1);
for (int i = 0; i < n; i++) {
if (events[i].data.fd == sockfd) {
char buf[1024];
while (1) {
ssize_t count = recv(sockfd, buf, sizeof(buf), 0);
if (count == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) break;
perror("recv");
break;
} else if (count == 0) {
printf("Connection closed
");
return 0;
} else {
// 处理接收到的数据
printf("Received data: %s
", buf);
}
}
}
}
}
close(epollfd);
close(sockfd);
return 0;
}
这个示例展示了如何使用epoll
来监视套接字,并在数据可读时使用非阻塞的recv
来读取数据。
没有搜到相关的文章