zoukankan      html  css  js  c++  java
  • select server

    server with select

      1 #include<stdio.h>
      2 #include<sys/types.h>
      3 #include<sys/socket.h>
      4 #include<unistd.h>
      5 #include<stdlib.h>
      6 #include<errno.h>
      7 #include<arpa/inet.h>
      8 #include<netinet/in.h>
      9 #include<string.h>
     10 #include<signal.h>
     11 #include<sys/wait.h>
     12 
     13 #define ERR_EXIT(m) 
     14     do { 
     15         perror(m); 
     16         exit(EXIT_FAILURE); 
     17     } while (0)
     18 
     19 
     20 int main(void)
     21 {
     22     
     23     signal(SIGPIPE, SIG_IGN);
     24     int listenfd; //被动套接字(文件描述符),即只可以accept, 监听套接字
     25     if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     26 //  listenfd = socket(AF_INET, SOCK_STREAM, 0)  
     27         ERR_EXIT("socket error");
     28 
     29     struct sockaddr_in servaddr;
     30     memset(&servaddr, 0, sizeof(servaddr));
     31     servaddr.sin_family = AF_INET;
     32     servaddr.sin_port = htons(5188);
     33     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
     34     /* servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); */
     35     /* inet_aton("127.0.0.1", &servaddr.sin_addr); */
     36     
     37     int on = 1;
     38     if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
     39         ERR_EXIT("setsockopt error");
     40 
     41     if (bind(listenfd, (struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
     42         ERR_EXIT("bind error");
     43 
     44     if (listen(listenfd, SOMAXCONN) < 0) //listen应在socket和bind之后,而在accept之前
     45         ERR_EXIT("listen error");
     46     
     47     struct sockaddr_in peeraddr; //传出参数
     48     socklen_t peerlen = sizeof(peeraddr); //传入传出参数,必须有初始值
     49     
     50     int conn; // 已连接套接字(变为主动套接字,即可以主动connect)
     51     int i;
     52     int client[FD_SETSIZE];
     53     int maxi = 0; // client数组中最大不空闲位置的下标
     54     for (i = 0; i < FD_SETSIZE; i++)
     55         client[i] = -1;
     56 
     57     int nready;
     58     int maxfd = listenfd;
     59     fd_set rset;
     60     fd_set allset;
     61     FD_ZERO(&rset);
     62     FD_ZERO(&allset);
     63     FD_SET(listenfd, &allset);
     64 
     65     while (1) {
     66         rset = allset;
     67         nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
     68         if (nready == -1) {
     69             if (errno == EINTR)
     70                 continue;
     71             ERR_EXIT("select error");
     72         }
     73 
     74         if (nready == 0)
     75             continue;
     76 
     77         if (FD_ISSET(listenfd, &rset)) {
     78         
     79             conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen);  //accept不再阻塞
     80             if (conn == -1)
     81                 ERR_EXIT("accept error");
     82             
     83             for (i = 0; i < FD_SETSIZE; i++) {
     84                 if (client[i] < 0) {
     85                     client[i] = conn;
     86                     if (i > maxi)
     87                         maxi = i;
     88                     break;
     89                 } 
     90             }
     91             
     92             if (i == FD_SETSIZE) {
     93                 fprintf(stderr, "too many clients
    ");
     94                 exit(EXIT_FAILURE);
     95             }
     96 
     97             printf("recv connect ip=%s port=%d
    ", inet_ntoa(peeraddr.sin_addr),
     98                 ntohs(peeraddr.sin_port));
     99 
    100             FD_SET(conn, &allset);
    101             if (conn > maxfd)
    102                 maxfd = conn;
    103 
    104             if (--nready <= 0)
    105                 continue;
    106         }
    107 
    108         for (i = 0; i <= maxi; i++) {
    109             conn = client[i];
    110             if (conn == -1)
    111                 continue;
    112 
    113             if (FD_ISSET(conn, &rset)) {
    114                 
    115                 char recvbuf[1024] = {0};
    116                 int ret = read(conn, recvbuf, 1024);
    117                 if (ret == -1)
    118                     ERR_EXIT("readline error");
    119                 else if (ret  == 0) { //客户端关闭 
    120                     printf("client close 
    ");
    121                     FD_CLR(conn, &allset);
    122                     client[i] = -1;
    123                     close(conn);
    124                 }
    125         
    126                 fputs(recvbuf, stdout);
    127                 write(conn, recvbuf, strlen(recvbuf));
    128                 
    129                 if (--nready <= 0)
    130                     break; 
    131             }
    132         }
    133 
    134 
    135     }
    136         
    137     return 0;
    138 }

    ref1      ref2

  • 相关阅读:
    Pyspider
    tornado websocket
    cookie、session、csrf
    python图片拼接
    SQLAlchemy查询
    tornado的ORM
    模板继承和UImodul 和 UImethods
    图像处理-05-浮雕效果处理
    图像处理-04-图像的黑白处理
    图像处理-03-实现图像的旋转
  • 原文地址:https://www.cnblogs.com/forcheryl/p/4664856.html
Copyright © 2011-2022 走看看