select
main() { int sock; FILE *fp; struct fd_set fds; struct timeval timeout={3,0}; //select等待3秒,3秒轮询,要非阻塞就置0 char buffer[256]={0}; //256字节的接收缓冲区 /* 假定已经建立UDP连接,具体过程不写,简单,当然TCP也同理,主机ip和port都已经给定,要写的文件已经打开 sock=socket(...); bind(...); fp=fopen(...); */ while(1) { FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化 FD_SET(sock,&fds); //添加描述符 FD_SET(fp,&fds); //同上 maxfdp=sock>fp?sock+1:fp+1; //描述符最大值加1 switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select使用 { case -1: exit(-1);break; //select错误,退出程序 case 0:break; //再次轮询 default: if(FD_ISSET(sock,&fds)) //测试sock是否可读,即是否网络上有数据 { recvfrom(sock,buffer,256,.....);//接受网络数据 if(FD_ISSET(fp,&fds)) //测试文件是否可写 fwrite(fp,buffer...);//写入文件 buffer清空; }// end if break; }// end switch }//end while }//end main
poll
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/tcp.h> #include <sys/select.h> #include <poll.h> #include <netdb.h> #include <limits.h> #define ip "192.168.188.133" #define port 8888 #define INFTIM 10000 int main(int argc, char* argv[]) { int afd, sfd; struct sockaddr_in servaddr; //创建socket文件描述符 sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd == -1) { perror("sfd == -1"); exit(1); } //防止端口复用 int reuse = 1 ; setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)); //初始化socket memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port) ; servaddr.sin_addr.s_addr = inet_addr(ip); //绑定套接字 if(bind(sfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { perror("bind error"); exit(1); } //监听套接字 if(listen(sfd, 5) == -1) { perror("listen error"); exit(1); } struct pollfd fdarr[4]; fdarr[0].fd = sfd; fdarr[0].events = POLLIN; for(int i = 1; i < 4; ++i) { fdarr[i].fd = -1; } int maxfd = sfd; int confd; int i = 1; while(1) { int flag = poll(fdarr, maxfd + 1, INFTIM); if(flag == -1) { perror("poll error"); exit(1); } if(fdarr[0].revents & POLLIN)//监听套接字可读 { confd = accept(sfd, NULL, NULL); for(i = 1; i < 4; ++i) { if(fdarr[i].fd == -1) { fdarr[i].fd = confd; fdarr[i].events = POLLIN; break; } } if(i == 4) { perror("too many client"); exit(1); } if(fdarr[i].fd > maxfd) { maxfd = fdarr[i].fd; } } for(i = 1; i < 4; ++i) { if(fdarr[i].fd == -1) { continue; } if(fdarr[i].revents & (POLLIN | POLLERR)) { int readn; char buf[10]; memset(buf, 0, 10); if((readn = read(fdarr[i].fd, buf, 10)) < 0) { if(errno == ECONNRESET) { close(fdarr[i].fd); fdarr[i].fd = -1; }else { perror("read error"); } }else if(readn == 0) { close(fdarr[i].fd); fdarr[i].fd = -1; }else { printf("%s ", buf); } } } } //关闭套接字 close(sfd); return 0; }