http://blog.csdn.net/robertkun/article/details/52269313
參考:http://www.cnblogs.com/Anker/p/3261006.html
使用poll實現的io多路復用服務端和客戶端。
客戶端通過子進程創建多個客戶端連接。
客戶端每隔1秒向服務端發送一個時間戳,
服務端接收到時間戳以后,保存在本地的文件中,
一個客戶端對應一個存儲文件,
并將接收到的時間戳返回給客戶端。
代碼:
服務端:
[cpp]?view plaincopy
- #include?<stdio.h>??
- #include?<stdlib.h>??
- #include?<string.h>??
- #include?<fcntl.h>??
- #include?<poll.h>??
- #include?<errno.h>??
- #include?<unistd.h>??
- ??
- #include?<sys/ioctl.h>??
- #include?<sys/types.h>??
- #include?<sys/socket.h>??
- #include?<sys/stat.h>??
- ??
- #include?<netinet/in.h>??
- #include?<arpa/inet.h>??
- ??
- ??
- #define?IP_ADDR?????"127.0.0.1"??
- #define?PORT????????59999??
- #define?LISTEN_Q????5??
- #define?OPEN_MAX????100000??
- #define?INFTIM??????-1??
- #define?MAX_LINE????1024??
- ??
- static?int?socket_bind(const?char*?ip,?int?port);??
- static?void?do_poll(int?ln_fd);??
- static?void?handle_conn(struct?pollfd*?conn_fds,?int?num,?int*?files);??
- ??
- int?main()??
- {??
- ????int?ln_fd,?cn_fd,?sk_fd?=?0;??
- ????struct?sockaddr_in?_addr;??
- ??
- ????socklen_t?_len;??
- ????ln_fd?=?socket_bind(IP_ADDR,?PORT);??
- ????listen(ln_fd,?LISTEN_Q);??
- ??
- ????do_poll(ln_fd);??
- ????return?0;??
- }??
- ??
- ??
- static?int?socket_bind(const?char*?ip,?int?port)??
- {??
- ????int?ln_fd;??
- ????struct?sockaddr_in?_addr;??
- ????ln_fd?=?socket(AF_INET,?SOCK_STREAM,?0);??
- ????if(ln_fd?==?-1)?{??
- ????????perror("socket?error!");??
- ????????exit(1);??????????
- ????}??
- ??
- ????bzero(&_addr,?sizeof(_addr));??
- ????_addr.sin_family?=?AF_INET;??
- ????inet_pton(AF_INET,?ip,?&_addr.sin_addr);??
- ????_addr.sin_port?=?htons(port);??
- ??
- ????if(bind(ln_fd,?(struct?sockaddr*)&_addr,?sizeof(_addr))?==?-1)?{??
- ????????perror("bind?error!");??
- ????????exit(1);??
- ????}??
- ??
- ????return?ln_fd;??
- }??
- ??
- static?void?do_poll(int?ln_fd)??
- {??
- ????int?connfd,?sockfd?=?0;??
- ????struct?sockaddr_in?_addr;??
- ????socklen_t?_len;??
- ????int?files[OPEN_MAX];??
- ????struct?pollfd?clients[OPEN_MAX];??
- ????int?nMax,?i,?nReady?=?0;??
- ??????
- ????clients[0].fd?=?ln_fd;??
- ????clients[0].events?=?POLLIN;??
- ??????
- ????for(i?=?1;?i<OPEN_MAX;?++i)?{??
- ????????clients[i].fd?=?-1;??
- ????}??
- ????nMax?=?0;??
- ??
- ????while(1)?{??
- ????????nReady?=?poll(clients,?nMax+1,?INFTIM);??
- ????????if(nReady?==?-1)?{??
- ????????????perror("poll?error!");??
- ????????????exit(1);??
- ????????}??
- ????????else?{??
- ????????????printf("poll?ready?num?=?%d\n",?nReady);??
- ????????}??
- ??
- ????????if(clients[0].revents?&?POLLIN)?{??
- ????????????_len?=?sizeof(_addr);??
- ????????????if((connfd?=?accept(ln_fd,?(struct?sockaddr*)&_addr,?&_len))?==?-1)?{??
- ????????????????if(errno?==?EINTR)?{??
- ????????????????????printf("EINTR!\n");??
- ????????????????????continue;??
- ????????????????}??
- ????????????????else?{??
- ????????????????????perror("accept?error!");??
- ????????????????????exit(1);??
- ????????????????}??
- ????????????}??
- ??
- ????????????fprintf(stdout,?"accept?a?new?client!?[%s]\n",?inet_ntoa(_addr.sin_addr));??
- ??
- ????????????for(i=1;?i<OPEN_MAX;?++i)?{??
- ????????????????if(clients[i].fd?<?0)?{??
- ????????????????????fcntl(connfd,?F_SETFL,?fcntl(connfd,F_GETFL)|?O_NONBLOCK);??
- ????????????????????unsigned?long?nVal=1;??
- ????????????????????ioctl(connfd,?FIONBIO,?&nVal);??
- ??
- ????????????????????clients[i].fd?=?connfd;??
- ????????????????????char?path[2048]?=?{"\0"};??
- ????????????????????getcwd(path,?sizeof(path));??
- ??????????????????????
- ????????????????????sprintf(path,?"%s/tmp_%d.txt",?path,?i);??
- ????????????????????printf("path=%s\n",?path);??
- ????????????????????int?fd?=?open(path,?O_RDWR|O_APPEND|O_CREAT,?0666);??
- ????????????????????if(fd?>?0)?{??
- ????????????????????????files[i]?=?fd;??
- ????????????????????}??
- ????????????????????else?{??
- ????????????????????????fprintf(stdout,?"open?file?error!?[%s]\n",?path);??
- ????????????????????????perror("open?file?error!");??
- ????????????????????}??
- ??
- ????????????????????break;??
- ????????????????}??
- ????????????}??
- ??
- ????????????fflush(stdout);??
- ??
- ????????????if(i?==?OPEN_MAX)?{??
- ????????????????fprintf(stderr,?"too?many?clients\n");??
- ????????????????exit(1);??
- ????????????}??
- ??
- ????????????clients[i].events?=?POLLIN;??
- ????????????nMax?=?(i?>?nMax???i?:?nMax);??
- ????????????if(--nReady?<=?0)?{??
- ????????????????printf("nReady?=?%d,?nMax?=?%d\n",?nReady,?nMax);??
- ????????????????continue;??
- ????????????}??
- ????????}??
- ??????????
- ????????handle_conn(clients,?nMax,?files);??
- ????}??
- }??
- ??
- static?void?handle_conn(struct?pollfd*?conn_fds,?int?num,?int*?files)??
- {??
- ????int?i,?n?=?0;??
- ????char?buf[MAX_LINE];??
- ????memset(buf,?0,?MAX_LINE);??
- ????for(i=1;?i<=num;?++i)??
- ????{??
- ????????if(conn_fds[i].fd?<?0)??
- ????????????continue;??
- ??
- ????????if(conn_fds[i].revents?&?POLLIN)?{??
- ????????????n?=?read(conn_fds[i].fd,?buf,?MAX_LINE);??
- ????????????if(n?==?0)?{??
- ????????????????close(conn_fds[i].fd);??
- ????????????????conn_fds[i].fd?=?-1;??
- ????????????????continue;??
- ????????????}??
- ??
- ????????????write(files[i],?buf,?n);??
- ????????????write(conn_fds[i].fd,?buf,?n);??
- ????????}??
- ????}??
- }??
客戶端:
[cpp]?view plaincopy
- #include?<stdio.h>??
- #include?<stdlib.h>??
- #include?<string.h>??
- ??
- #include?<unistd.h>??
- #include?<sys/types.h>??
- #include?<sys/socket.h>??
- ??
- #include?<netinet/in.h>??
- #include?<poll.h>??
- #include?<errno.h>??
- #include?<arpa/inet.h>??
- ??
- #define?MAX_LINE????1024??
- #define?IP_ADDR?????"127.0.0.1"??
- #define?SERV_PORT???59999??
- ??
- #define?max(a,b)?(a>b)?a:b??
- ??
- static?void?do_conn();??
- static?void?handle_conn(int?sockfd);??
- ??
- int?main(int?args,?char*?argv[])??
- {??
- ????int?i?=?0;??
- ????for(i=0;?i<2000;?++i)?{??
- ????????pid_t?fpid?=?-1;??
- ????????fpid?=?fork();??
- ????????if(fpid?<?0)?{??
- ????????????printf("error?in?fork!");??
- ????????}??
- ????????else?if(fpid?==?0)?{??
- ????????????do_conn();??
- ????????}??
- ????????else?{??
- ????????????//do_conn();??
- ????????}??
- ????}??
- ??
- ????return?0;??
- }??
- ??
- static?void?do_conn()??
- {??
- ????int?sockfd;??
- ????struct?sockaddr_in?_addr;??
- ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);??
- ??
- ????bzero(&_addr,?sizeof(_addr));??
- ????_addr.sin_family?=?AF_INET;??
- ????_addr.sin_port?=?htons(SERV_PORT);??
- ??
- ????inet_pton(AF_INET,?IP_ADDR,?&_addr.sin_addr);??
- ????int?ret?=?connect(sockfd,?(struct?sockaddr*)&_addr,?sizeof(_addr));??
- ????if(ret?<?0)?{??
- ????????perror("connect?failed!");??
- ????????exit(1);??
- ????}??
- ??
- ????handle_conn(sockfd);??
- }??
- ??
- static?void?handle_conn(int?sockfd)??
- {??
- ????char?send_line[MAX_LINE]?=?{'\0'};??
- ????char?recv_line[MAX_LINE]?=?{'\0'};??
- ??
- ????struct?pollfd?pfds[1];??
- ????pfds[0].fd?=?sockfd;??
- ????pfds[0].events?=?POLLIN|POLLOUT;??
- ??
- ????while(1)?{??
- ????????poll(pfds,?1,?1000);??
- ????????if(pfds[0].revents?&?POLLIN)?{??
- ????????????int?ret?=?read(sockfd,?recv_line,?MAX_LINE);??
- ????????????if(ret?==?0)?{??
- ????????????????perror("client:?server?is?closed.");??
- ????????????????close(sockfd);??
- ????????????????continue;??
- ????????????}??
- ????????????else?if(ret?<?0)?{??
- ????????????????perror("client:?read?error!");??
- ????????????????continue;??
- ????????????}??
- ??
- ????????????//printf("[%d]?recv=%s\n",?(int)getpid(),?recv_line);??
- ????????}??
- ??
- ????????if(pfds[0].revents?&?POLLOUT)?{??
- ????????????time_t?_time?=?time(0);??
- ????????????char?dt[20]={"\0"};??
- ????????????sprintf(dt,?"%d\n",?_time);??
- ??
- ????????????memcpy(send_line,?dt,?strlen(dt));??
- ????????????int?ret?=?write(sockfd,?send_line,?strlen(send_line));??
- ????????????if(ret?<?0)?{??
- ????????????????perror("write?error!!");??
- ????????????}??
- ????????}??
- ??
- ????????sleep(1);??
- ????}??
- ??
- ????shutdown(sockfd,?SHUT_WR);??
- }??