• 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 ", 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 ", 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... ", errno);
    61.         exit(EXIT_FAILURE);
    62.     }
    63.     //!> 设置非阻塞模式
    64.     //!>
    65.     if (setnonblocking(listen_fd) == -1) {
    66.         printf("Setnonblocking Error : %d ", 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 ", errno);
    73.         exit(EXIT_FAILURE);
    74.     }
    75.     //!> 监听
    76.     //!>
    77.     if (listen(listen_fd, MAXBACK) == -1) {
    78.         printf("Listen Error : %d ", 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 ", 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 ", 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 ", errno);
    102.                     exit(EXIT_FAILURE);
    103.                 }

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

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

    61.             memset(send, 0, sizeof(send));
    62.             if (fgets(send, MAXLINE, fp) == NULL) {
    63.                 printf("End... ");
    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.. ");
    72.                     return;
    73.                 }

    74.                 printf("Client send : %s ", 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 ! ");
    88.         exit(EXIT_FAILURE);
    89.     }
    90.     //!> 建立套接字
    91.     if ((connfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    92.         printf("Socket Error... ", 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.. ");
    103.         exit(EXIT_FAILURE);
    104.     }
    105.     /*else
    106.      {
    107.      printf("Connet ok.. ");
    108.      } */

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

    112.     //!>

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

    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) |
    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    1 TKinter小窗口及标题
    css之padding,marging
    css之opacity
    css之position
    Leetcode 1368 使网格图至少有一条有效路径的最小代价
    Leetcode 137 只出现一次的数字II
    Leetcode 135分发糖果
    Leetcode 134加油站
    Leetcode 124 二叉树的最大路径和
    Leetcode 5346 二叉树中的列表
  • 原文地址:https://www.cnblogs.com/ztguang/p/12649512.html
Copyright © 2020-2023  润新知