zoukankan      html  css  js  c++  java
  • 用 select 实现处理多连接的异步通讯服务器

    因为对于任何句柄 ( file descriptor ) select 函数都能检测出其状态变化,对于用于 listen 的 socket 也是一样。

    只要把用于 listen 的 socket 加入 ( FD_SET ) 到 select 检测的集合里,当有连接到来时 select 就能判断到。因为 select 函数能处理的是句柄集合,所以加入这样一个 socket 并不与 select 判断其它 socket 的状态有任何冲突。

    • 实现片段代码:

    #define MAX_NUM_ONLINE_SOCKET 100

    int lsn_sock_fd;

    int client_sock_fd[MAX_NUM_ONLINE_SOCKET];

    fd_set rdfds;

    int maxfds;

    int tmp_fd;

    struct time tv;

    int retval;

    int i;

    maxfds = -1;

    for(i = 0; i < MAX_NUM_ONLINE_SOCKET; i++) client_sock_fd[i] = -1;

    lsn_sock_fd = socket(AF_INET, SOCK_STREAM, 0);

    /* 设置监听的地址和端口 */

    /* 调用 bind 把地址信息与 socket 绑定到一起 */

    listen(lsn_sock_fd, 2);

    while(1) {

        maxfds = 0;

        FD_ZERO(&rdfds);

        if(lsn_sock_fd > 0) {

            FD_SET(lsn_sock_fd, &rdfds); /* 在这里把用于 listen 的 socket 加入到 select 判断的句柄集合里来 */

            if( lsn_sock_fd > maxfds) maxfds = lsn_sock_fd;

        }
        for(i = 0; i < MAX_NUM_ONLINE_SOCKET; i++) {

            if(client_sock_fd[i] > 0) {

              FD_SET(client_sock_fd[i], &rdfds); /* 把所有在线客户端连接加入到 select 检测的集合中来 */

          if( client_sock_fd[i] > maxfds) maxfds = client_sock_fd[i];

            }

        }

        tv.tv_sec = 1;

        tv.tv_usec = 0;

        if(maxfds < 1) continue;

        retval = select(maxfds + 1, &rfds, NULL, NULL, &tv);
        if(retval < 0) {

            printf("select 出错,错误编号:%d,错误信息:%s ", errno, strerror(errno));

            break;

        }

        else if(!retval) continue; /* listen 的 socket 上没有任何连接到来,在线的所有连接上也没有任何一个上有数据到来 */

        if(FD_ISSET(lsn_sock_fd, &rdfds)) { /* 说明 listen 的 socket 上有新的连接到来了 */

            tmp_fd = accept(lsn_sock_fd, ......);

            for(i = 0; i < MAX_NUM_ONLINE_SOCKET; i++) {

                if(client_sock_fd[i] < 0) {

                    client_sock_fd[i] = tmp_fd;

                    break;

    }

            }

             if(i == MAX_NUM_ONLINE_SOCKET) {

                    printf("连接太多了,我最多只能接受%d个连接同时在线 ", MAX_NUM_ONLINE_SOCKET);  

                    close(tmp_fd);

             }
        }
        for(i = 0; i < MAX_NUM_ONLINE_SOCKET; i++) {

            if(FD_ISSET(client_sock_fd[i], &rdfds)) { /* 说明第 i 个客户端连接上有数据到来了 */

                 recv(client_sock_fd[i], ......);
                 /* 对这个连接进行其它操作 */
                 send(client_sock_fd[i], ......);

                 /* 如果这个连接处理完毕了就要 close 它,并执行 client_sock_fd[i] = -1 ; */
            }

    }

    }

    From:http://hi.baidu.com/beibeiboo/item/3b6e0ecb7e6d0f50ac00ef7a

  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/ganrui/p/3704268.html
Copyright © 2011-2022 走看看