使用poll实现的io多路复用服务端和客户端

http://blog.csdn.net/robertkun/article/details/52269313

参考:http://www.cnblogs.com/Anker/p/3261006.html


使用poll实现的io多路复用服务端和客户端。

客户端通过子进程创建多个客户端连接。

客户端每隔1秒向服务端发送一个时间戳,

服务端接收到时间戳以后,保存在本地的文件中,

一个客户端对应一个存储文件,

并将接收到的时间戳返回给客户端。


代码:

服务端:

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <fcntl.h>  
  5. #include <poll.h>  
  6. #include <errno.h>  
  7. #include <unistd.h>  
  8.   
  9. #include <sys/ioctl.h>  
  10. #include <sys/types.h>  
  11. #include <sys/socket.h>  
  12. #include <sys/stat.h>  
  13.   
  14. #include <netinet/in.h>  
  15. #include <arpa/inet.h>  
  16.   
  17.   
  18. #define IP_ADDR     "127.0.0.1"  
  19. #define PORT        59999  
  20. #define LISTEN_Q    5  
  21. #define OPEN_MAX    100000  
  22. #define INFTIM      -1  
  23. #define MAX_LINE    1024  
  24.   
  25. static int socket_bind(const char* ip, int port);  
  26. static void do_poll(int ln_fd);  
  27. static void handle_conn(struct pollfd* conn_fds, int num, int* files);  
  28.   
  29. int main()  
  30. {  
  31.     int ln_fd, cn_fd, sk_fd = 0;  
  32.     struct sockaddr_in _addr;  
  33.   
  34.     socklen_t _len;  
  35.     ln_fd = socket_bind(IP_ADDR, PORT);  
  36.     listen(ln_fd, LISTEN_Q);  
  37.   
  38.     do_poll(ln_fd);  
  39.     return 0;  
  40. }  
  41.   
  42.   
  43. static int socket_bind(const char* ip, int port)  
  44. {  
  45.     int ln_fd;  
  46.     struct sockaddr_in _addr;  
  47.     ln_fd = socket(AF_INET, SOCK_STREAM, 0);  
  48.     if(ln_fd == -1) {  
  49.         perror("socket error!");  
  50.         exit(1);          
  51.     }  
  52.   
  53.     bzero(&_addr, sizeof(_addr));  
  54.     _addr.sin_family = AF_INET;  
  55.     inet_pton(AF_INET, ip, &_addr.sin_addr);  
  56.     _addr.sin_port = htons(port);  
  57.   
  58.     if(bind(ln_fd, (struct sockaddr*)&_addr, sizeof(_addr)) == -1) {  
  59.         perror("bind error!");  
  60.         exit(1);  
  61.     }  
  62.   
  63.     return ln_fd;  
  64. }  
  65.   
  66. static void do_poll(int ln_fd)  
  67. {  
  68.     int connfd, sockfd = 0;  
  69.     struct sockaddr_in _addr;  
  70.     socklen_t _len;  
  71.     int files[OPEN_MAX];  
  72.     struct pollfd clients[OPEN_MAX];  
  73.     int nMax, i, nReady = 0;  
  74.       
  75.     clients[0].fd = ln_fd;  
  76.     clients[0].events = POLLIN;  
  77.       
  78.     for(i = 1; i<OPEN_MAX; ++i) {  
  79.         clients[i].fd = -1;  
  80.     }  
  81.     nMax = 0;  
  82.   
  83.     while(1) {  
  84.         nReady = poll(clients, nMax+1, INFTIM);  
  85.         if(nReady == -1) {  
  86.             perror("poll error!");  
  87.             exit(1);  
  88.         }  
  89.         else {  
  90.             printf("poll ready num = %d\n", nReady);  
  91.         }  
  92.   
  93.         if(clients[0].revents & POLLIN) {  
  94.             _len = sizeof(_addr);  
  95.             if((connfd = accept(ln_fd, (struct sockaddr*)&_addr, &_len)) == -1) {  
  96.                 if(errno == EINTR) {  
  97.                     printf("EINTR!\n");  
  98.                     continue;  
  99.                 }  
  100.                 else {  
  101.                     perror("accept error!");  
  102.                     exit(1);  
  103.                 }  
  104.             }  
  105.   
  106.             fprintf(stdout, "accept a new client! [%s]\n", inet_ntoa(_addr.sin_addr));  
  107.   
  108.             for(i=1; i<OPEN_MAX; ++i) {  
  109.                 if(clients[i].fd < 0) {  
  110.                     fcntl(connfd, F_SETFL, fcntl(connfd,F_GETFL)| O_NONBLOCK);  
  111.                     unsigned long nVal=1;  
  112.                     ioctl(connfd, FIONBIO, &nVal);  
  113.   
  114.                     clients[i].fd = connfd;  
  115.                     char path[2048] = {"\0"};  
  116.                     getcwd(path, sizeof(path));  
  117.                       
  118.                     sprintf(path, "%s/tmp_%d.txt", path, i);  
  119.                     printf("path=%s\n", path);  
  120.                     int fd = open(path, O_RDWR|O_APPEND|O_CREAT, 0666);  
  121.                     if(fd > 0) {  
  122.                         files[i] = fd;  
  123.                     }  
  124.                     else {  
  125.                         fprintf(stdout, "open file error! [%s]\n", path);  
  126.                         perror("open file error!");  
  127.                     }  
  128.   
  129.                     break;  
  130.                 }  
  131.             }  
  132.   
  133.             fflush(stdout);  
  134.   
  135.             if(i == OPEN_MAX) {  
  136.                 fprintf(stderr, "too many clients\n");  
  137.                 exit(1);  
  138.             }  
  139.   
  140.             clients[i].events = POLLIN;  
  141.             nMax = (i > nMax ? i : nMax);  
  142.             if(--nReady <= 0) {  
  143.                 printf("nReady = %d, nMax = %d\n", nReady, nMax);  
  144.                 continue;  
  145.             }  
  146.         }  
  147.           
  148.         handle_conn(clients, nMax, files);  
  149.     }  
  150. }  
  151.   
  152. static void handle_conn(struct pollfd* conn_fds, int num, int* files)  
  153. {  
  154.     int i, n = 0;  
  155.     char buf[MAX_LINE];  
  156.     memset(buf, 0, MAX_LINE);  
  157.     for(i=1; i<=num; ++i)  
  158.     {  
  159.         if(conn_fds[i].fd < 0)  
  160.             continue;  
  161.   
  162.         if(conn_fds[i].revents & POLLIN) {  
  163.             n = read(conn_fds[i].fd, buf, MAX_LINE);  
  164.             if(n == 0) {  
  165.                 close(conn_fds[i].fd);  
  166.                 conn_fds[i].fd = -1;  
  167.                 continue;  
  168.             }  
  169.   
  170.             write(files[i], buf, n);  
  171.             write(conn_fds[i].fd, buf, n);  
  172.         }  
  173.     }  
  174. }  

客户端:

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. #include <unistd.h>  
  6. #include <sys/types.h>  
  7. #include <sys/socket.h>  
  8.   
  9. #include <netinet/in.h>  
  10. #include <poll.h>  
  11. #include <errno.h>  
  12. #include <arpa/inet.h>  
  13.   
  14. #define MAX_LINE    1024  
  15. #define IP_ADDR     "127.0.0.1"  
  16. #define SERV_PORT   59999  
  17.   
  18. #define max(a,b) (a>b)?a:b  
  19.   
  20. static void do_conn();  
  21. static void handle_conn(int sockfd);  
  22.   
  23. int main(int args, char* argv[])  
  24. {  
  25.     int i = 0;  
  26.     for(i=0; i<2000; ++i) {  
  27.         pid_t fpid = -1;  
  28.         fpid = fork();  
  29.         if(fpid < 0) {  
  30.             printf("error in fork!");  
  31.         }  
  32.         else if(fpid == 0) {  
  33.             do_conn();  
  34.         }  
  35.         else {  
  36.             //do_conn();  
  37.         }  
  38.     }  
  39.   
  40.     return 0;  
  41. }  
  42.   
  43. static void do_conn()  
  44. {  
  45.     int sockfd;  
  46.     struct sockaddr_in _addr;  
  47.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  48.   
  49.     bzero(&_addr, sizeof(_addr));  
  50.     _addr.sin_family = AF_INET;  
  51.     _addr.sin_port = htons(SERV_PORT);  
  52.   
  53.     inet_pton(AF_INET, IP_ADDR, &_addr.sin_addr);  
  54.     int ret = connect(sockfd, (struct sockaddr*)&_addr, sizeof(_addr));  
  55.     if(ret < 0) {  
  56.         perror("connect failed!");  
  57.         exit(1);  
  58.     }  
  59.   
  60.     handle_conn(sockfd);  
  61. }  
  62.   
  63. static void handle_conn(int sockfd)  
  64. {  
  65.     char send_line[MAX_LINE] = {'\0'};  
  66.     char recv_line[MAX_LINE] = {'\0'};  
  67.   
  68.     struct pollfd pfds[1];  
  69.     pfds[0].fd = sockfd;  
  70.     pfds[0].events = POLLIN|POLLOUT;  
  71.   
  72.     while(1) {  
  73.         poll(pfds, 1, 1000);  
  74.         if(pfds[0].revents & POLLIN) {  
  75.             int ret = read(sockfd, recv_line, MAX_LINE);  
  76.             if(ret == 0) {  
  77.                 perror("client: server is closed.");  
  78.                 close(sockfd);  
  79.                 continue;  
  80.             }  
  81.             else if(ret < 0) {  
  82.                 perror("client: read error!");  
  83.                 continue;  
  84.             }  
  85.   
  86.             //printf("[%d] recv=%s\n", (int)getpid(), recv_line);  
  87.         }  
  88.   
  89.         if(pfds[0].revents & POLLOUT) {  
  90.             time_t _time = time(0);  
  91.             char dt[20]={"\0"};  
  92.             sprintf(dt, "%d\n", _time);  
  93.   
  94.             memcpy(send_line, dt, strlen(dt));  
  95.             int ret = write(sockfd, send_line, strlen(send_line));  
  96.             if(ret < 0) {  
  97.                 perror("write error!!");  
  98.             }  
  99.         }  
  100.   
  101.         sleep(1);  
  102.     }  
  103.   
  104.     shutdown(sockfd, SHUT_WR);  
  105. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值