epoll—linux c language —TCP unicast

http://blog.csdn.net/shanshanpt/article/details/7383400

server.c

点击(此处)折叠或打开

  1. // gcc server.c -o server
  2. // indent -npro -kr -i8 -ts8 -sob -l280 -ss -ncs -cp1 *

  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <errno.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>        /* socket类定义需要 */
  11. #include <sys/epoll.h>        /* epoll头文件 */
  12. #include <fcntl.h>        /* nonblocking需要 */
  13. #include <sys/resource.h>    /* 设置最大的连接数需要setrlimit */

  14. #define MAXEPOLL 10000    /* 对于服务器来说,这个值可以很大的! */
  15. #define MAXLINE 1024
  16. #define PORT 6000
  17. #define MAXBACK 1000

  18. //!> 设置非阻塞
  19. //!>
  20. int setnonblocking(int fd)
  21. {
  22.     if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK) == -1) {
  23.         printf("Set blocking error : %d\n", errno);
  24.         return -1;
  25.     }
  26.     return 0;
  27. }

  28. int main(int argc, char **argv)
  29. {
  30.     int listen_fd;
  31.     int conn_fd;
  32.     int epoll_fd;
  33.     int nread;
  34.     int cur_fds;        //!> 当前已经存在的数量
  35.     int wait_fds;        //!> epoll_wait 的返回值
  36.     int i;
  37.     struct sockaddr_in servaddr;
  38.     struct sockaddr_in cliaddr;
  39.     struct epoll_event ev;
  40.     struct epoll_event evs[MAXEPOLL];
  41.     struct rlimit rlt;    //!> 设置连接数所需
  42.     char buf[MAXLINE];
  43.     socklen_t len = sizeof(struct sockaddr_in);

  44.     //!> 设置每个进程允许打开的最大文件数
  45.     //!> 每个主机是不一样的哦,一般服务器应该很大吧!
  46.     //!>
  47.     rlt.rlim_max = rlt.rlim_cur = MAXEPOLL;
  48.     if (setrlimit(RLIMIT_NOFILE, &rlt) == -1) {
  49.         printf("Setrlimit Error : %d\n", errno);
  50.         exit(EXIT_FAILURE);
  51.     }
  52.     //!> server 套接口
  53.     //!>
  54.     bzero(&servaddr, sizeof(servaddr));
  55.     servaddr.sin_family = AF_INET;
  56.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  57.     servaddr.sin_port = htons(PORT);

  58.     //!> 建立套接字
  59.     if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  60.         printf("Socket Error...\n", errno);
  61.         exit(EXIT_FAILURE);
  62.     }
  63.     //!> 设置非阻塞模式
  64.     //!>
  65.     if (setnonblocking(listen_fd) == -1) {
  66.         printf("Setnonblocking Error : %d\n", errno);
  67.         exit(EXIT_FAILURE);
  68.     }
  69.     //!> 绑定
  70.     //!>
  71.     if (bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) == -1) {
  72.         printf("Bind Error : %d\n", errno);
  73.         exit(EXIT_FAILURE);
  74.     }
  75.     //!> 监听
  76.     //!>
  77.     if (listen(listen_fd, MAXBACK) == -1) {
  78.         printf("Listen Error : %d\n", errno);
  79.         exit(EXIT_FAILURE);
  80.     }
  81.     //!> 创建epoll
  82.     //!>
  83.     epoll_fd = epoll_create(MAXEPOLL);    //!> create
  84.     ev.events = EPOLLIN | EPOLLET;    //!> accept
  85.     ev.data.fd = listen_fd;    //!> 将listen_fd 加入
  86.     if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0) {
  87.         printf("Epoll Error : %d\n", errno);
  88.         exit(EXIT_FAILURE);
  89.     }
  90.     cur_fds = 1;

  91.     while (1) {
  92.         if ((wait_fds = epoll_wait(epoll_fd, evs, cur_fds, -1)) == -1) {
  93.             printf("Epoll Wait Error : %d\n", errno);
  94.             exit(EXIT_FAILURE);
  95.         }

  96.         for (i = 0; i < wait_fds; i++) {
  97.             if (evs[i].data.fd == listen_fd && cur_fds < MAXEPOLL)
  98.                 //!> if是监听端口有事
  99.             {
  100.                 if ((conn_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &len)) == -1) {
  101.                     printf("Accept Error : %d\n", errno);
  102.                     exit(EXIT_FAILURE);
  103.                 }

  104.                 printf("Server get from client !\n" /*, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port */ );

  105.                 ev.events = EPOLLIN | EPOLLET;    //!> accept
  106.                 ev.data.fd = conn_fd;    //!> 将conn_fd 加入
  107.                 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {
  108.                     printf("Epoll Error : %d\n", errno);
  109.                     exit(EXIT_FAILURE);
  110.                 }
  111.                 ++cur_fds;
  112.                 continue;
  113.             }
  114.             //!> 下面处理数据
  115.             //!>
  116.             nread = read(evs[i].data.fd, buf, sizeof(buf));
  117.             if (nread <= 0)    //!> 结束后者出错
  118.             {
  119.                 close(evs[i].data.fd);
  120.                 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evs[i].data.fd, &ev);    //!> 删除计入的fd
  121.                 --cur_fds;    //!> 减少一个呗!
  122.                 continue;
  123.             }

  124.             write(evs[i].data.fd, buf, nread);    //!> 回写

  125.         }
  126.     }

  127.     close(listen_fd);
  128.     return 0;
  129. }

client.c

点击(此处)折叠或打开

  1. // gcc client.c -o client
  2. // indent -npro -kr -i8 -ts8 -sob -l280 -ss -ncs -cp1 *

  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <netinet/in.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <arpa/inet.h>
  12. #include <sys/select.h>

  13. #define MAXLINE 1024
  14. #define SERV_PORT 6000

  15. //!> 注意输入是由stdin,接受是由server发送过来
  16. //!> 所以在client端也是需要select进行处理的
  17. void send_and_recv(int connfd)
  18. {
  19.     FILE *fp = stdin;
  20.     int lens;
  21.     char send[MAXLINE];
  22.     char recv[MAXLINE];
  23.     fd_set rset;
  24.     FD_ZERO(&rset);
  25.     int maxfd = (fileno(fp) > connfd ? fileno(fp) : connfd + 1);
  26.     //!> 输入和输出的最大值
  27.     int n;

  28.     while (1) {
  29.         FD_SET(fileno(fp), &rset);
  30.         FD_SET(connfd, &rset);    //!> 注意不要把rset看作是简单的一个变量
  31.         //!> 注意它其实是可以包含一组套接字的哦,
  32.         //!> 相当于是封装的数组!每次都要是新的哦!

  33.         if (select(maxfd, &rset, NULL, NULL, NULL) == -1) {
  34.             printf("Client Select Error..\n");
  35.             exit(EXIT_FAILURE);
  36.         }
  37.         //!> if 连接口有信息
  38.         if (FD_ISSET(connfd, &rset))    //!> if 连接端口有信息
  39.         {
  40.             printf("client get from server ...\n");
  41.             memset(recv, 0, sizeof(recv));
  42.             n = read(connfd, recv, MAXLINE);
  43.             if (n == 0) {
  44.                 printf("Recv ok...\n");
  45.                 break;
  46.             } else if (n == -1) {
  47.                 printf("Recv error...\n");
  48.                 break;
  49.             } else {
  50.                 lens = strlen(recv);
  51.                 recv[lens] = '\0';
  52.                 //!> 写到stdout
  53.                 write(STDOUT_FILENO, recv, MAXLINE);
  54.                 printf("\n");
  55.             }

  56.         }
  57.         //!> if 有stdin输入
  58.         if (FD_ISSET(fileno(fp), &rset))    //!> if 有输入
  59.         {
  60.             //!> printf("client stdin ...\n");

  61.             memset(send, 0, sizeof(send));
  62.             if (fgets(send, MAXLINE, fp) == NULL) {
  63.                 printf("End...\n");
  64.                 exit(EXIT_FAILURE);
  65.             } else {
  66.                 //!>if( str )
  67.                 lens = strlen(send);
  68.                 send[lens - 1] = '\0';    //!> 减一的原因是不要回车字符
  69.                 //!> 经验值:这一步非常重要的哦!!!!!!!!
  70.                 if (strcmp(send, "q") == 0) {
  71.                     printf("Bye..\n");
  72.                     return;
  73.                 }

  74.                 printf("Client send : %s\n", send);
  75.                 write(connfd, send, strlen(send));
  76.             }
  77.         }

  78.     }

  79. }

  80. int main(int argc, char **argv)
  81. {
  82.     //!> char * SERV_IP = "10.30.97.188";
  83.     char buf[MAXLINE];
  84.     int connfd;
  85.     struct sockaddr_in servaddr;

  86.     if (argc != 2) {
  87.         printf("Input server ip !\n");
  88.         exit(EXIT_FAILURE);
  89.     }
  90.     //!> 建立套接字
  91.     if ((connfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  92.         printf("Socket Error...\n", errno);
  93.         exit(EXIT_FAILURE);
  94.     }
  95.     //!> 套接字信息
  96.     bzero(&servaddr, sizeof(servaddr));
  97.     servaddr.sin_family = AF_INET;
  98.     servaddr.sin_port = htons(SERV_PORT);
  99.     inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

  100.     //!> 链接server
  101.     if (connect(connfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
  102.         printf("Connect error..\n");
  103.         exit(EXIT_FAILURE);
  104.     }
  105.     /*else
  106.      {
  107.      printf("Connet ok..\n");
  108.      } */

  109.     //!>
  110.     //!> send and recv
  111.     send_and_recv(connfd);

  112.     //!>

  113.     close(connfd);
  114.     printf("Exit\n");

  115.     return 0;
  116. }

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(98) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
posted @ 2016-02-01 00:00  张同光  阅读(93)  评论(0编辑  收藏  举报