非阻塞recv
EAGAIN、EWOULDBLOCK错误码值11
返回值 |
含义 |
>0 |
接收字节数 |
0 |
接收FIN包,连接被对端断开 |
-1 |
(errno==EAGAIN||EWOULDBLOCK)表示还有数据未读。反之,则表示发生了错误。 |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <arpa/inet.h> |
| #include <sys/socket.h> |
| #include <errno.h> |
| #include <vector> |
| #include <time.h> |
| #include <sys/epoll.h> |
| #include <fcntl.h> |
| |
| #define MAXEVENTS 100 |
| |
| int InitServer(const unsigned int port); |
| |
| int setnoblocking(int fd); |
| |
| bool addfd(int epollfd, int fd, struct epoll_event* ev); |
| |
| bool addfdET(int epollfd, int fd, struct epoll_event* ev); |
| |
| int main(int argc,char** argv) |
| { |
| int listenfd=InitServer(atoi(argv[1])); |
| printf("listenfd=%d\n",listenfd); |
| if(listenfd==-1) |
| { |
| printf("InitServer failed..\n"); |
| return -1; |
| } |
| |
| |
| int epollfd=epoll_create(1); |
| if(epollfd<0) printf("epoll_create failed..\n"); |
| |
| |
| struct epoll_event ev; |
| addfd(epollfd, listenfd, &ev); |
| |
| while(true) |
| { |
| struct epoll_event events[MAXEVENTS]; |
| int infds=epoll_wait(epollfd,events,MAXEVENTS,-1); |
| if(infds<0) |
| { |
| printf("epoll_wait failed..\n"); |
| break; |
| } |
| if(infds==0) |
| { |
| printf("timeout..\n"); |
| break; |
| } |
| |
| |
| for(int i=0;i<infds;i++) |
| { |
| |
| if((events[i].data.fd==listenfd) && (events[i].events&EPOLLIN)) |
| { |
| struct sockaddr_in client_addr; |
| socklen_t client_addr_size=sizeof(client_addr); |
| int clientfd = accept(listenfd, (struct sockaddr*)&client_addr,&client_addr_size); |
| if(clientfd<0) |
| { |
| printf("accept failed..\n"); |
| continue; |
| } |
| |
| |
| |
| addfdET(epollfd,clientfd,&ev); |
| continue; |
| } |
| else if(events[i].events&EPOLLIN) |
| { |
| |
| while(true) |
| { |
| char buf[1024]; |
| memset(buf,0,sizeof(buf)); |
| int isize = recv(events[i].data.fd,buf,sizeof(buf),0); |
| |
| if(isize==0) |
| { |
| printf("对端关闭连接\n"); |
| memset(&ev,0,sizeof(struct epoll_event)); |
| ev.data.fd=events[i].data.fd; |
| ev.events=EPOLLIN; |
| epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,&ev); |
| close(events[i].data.fd); |
| printf("%ld client(%d) disconneted..\n",time(0),events[i].data.fd); |
| break; |
| } |
| else if(isize==-1) |
| { |
| if((errno==EAGAIN) || (errno==EWOULDBLOCK)) |
| { |
| errno=0; |
| continue; |
| } |
| else |
| { |
| |
| break; |
| } |
| |
| } |
| |
| printf("client(%d)recv msg:%s,size=%d\n",events[i].data.fd,buf,isize); |
| |
| |
| fd_set tmpfd; |
| FD_ZERO(&tmpfd); |
| FD_SET(events[i].data.fd,&tmpfd); |
| if(select(events[i].data.fd+1,0,&tmpfd,0,0)<0) |
| { |
| printf("没有可写数据的fd\n"); |
| break; |
| } |
| if(write(events[i].data.fd,buf,strlen(buf))<0) |
| { |
| printf("write failed..\n"); |
| close(events[i].data.fd); |
| break; |
| } |
| |
| } |
| } |
| |
| } |
| } |
| return 0; |
| } |
| |
| int InitServer(const unsigned int port) |
| { |
| int sockfd=-1; |
| sockfd = socket(PF_INET, SOCK_STREAM, 0); |
| if(sockfd == -1) return -1; |
| |
| int opt=1; |
| unsigned int len=sizeof(opt); |
| setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, len); |
| |
| struct sockaddr_in server_addr; |
| memset(&server_addr, 0, sizeof(server_addr)); |
| server_addr.sin_family=AF_INET; |
| server_addr.sin_addr.s_addr=htonl(INADDR_ANY); |
| server_addr.sin_port=htons(port); |
| |
| if(bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1) |
| { |
| close(sockfd); |
| sockfd=-1; |
| return -1; |
| } |
| |
| if(listen(sockfd, 5) == -1) |
| { |
| close(sockfd); |
| sockfd=-1; |
| return -1; |
| } |
| |
| return sockfd; |
| } |
| |
| int setnoblocking(int fd) |
| { |
| int flags = fcntl(fd, F_GETFL, 0); |
| if (flags == -1) |
| { |
| return -1; |
| } |
| |
| flags |= O_NONBLOCK; |
| if (fcntl(fd, F_SETFL, flags) == -1) |
| { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| bool addfd(int epollfd, int fd, struct epoll_event* ev) |
| { |
| memset(ev,0,sizeof(struct epoll_event)); |
| ev->data.fd=fd; |
| ev->events=EPOLLIN; |
| |
| return 0==epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,ev); |
| } |
| |
| bool addfdET(int epollfd, int fd, struct epoll_event* ev) |
| { |
| memset(ev,0,sizeof(struct epoll_event)); |
| ev->data.fd=fd; |
| ev->events=EPOLLIN|EPOLLET; |
| setnoblocking(fd); |
| return 0==epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,ev); |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)