select函数的单进程和TCP回射服务器应用模型


关于select的tcp回射服务器模型如下

#include "unp.h"
#define MAXLINE 4096
int main(int argc, char **argv)
{
    char sendbuf[MAXLINE], recvbuf[MAXLINE];
    int listenfd, maxfd,clientfd, sockfd;
    int maxi = 0, i;
    int client[FD_SETSIZE];
    size_t n;
    fd_set rset, allset;
    int readnum;
    FD_ZERO(&rset);
    FD_ZERO(&allset);
    for(i = 0; i < FD_SETSIZE; ++i){
        client[i] = -1;
    }

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in seraddr, cliaddr;
    bzero(&seraddr, sizeof(seraddr));
    seraddr.sin_family = AF_INET;
    seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    seraddr.sin_port = htonl(SERV_PORT);

    Bind(listenfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
    Listen(listenfd, LISTENQ);
    maxi = 0;
    FD_SET(listenfd, &allset);
    for(;;){
        rset = allset;
        readnum = Select(maxfd + 1, &rset, NULL, NULL, NULL);
        if(FD_ISSET(listenfd, &rset)){
            socklen_t clilen = sizeof(cliaddr);
            clientfd = Accept(listenfd, (struct sockaddr *)& cliaddr, &clilen);
            for(i = 0; i < FD_SETSIZE;++i){
                if(client[i] < 0){
                    client[i] = clientfd;
                    break;
                }
            }
            if(i == FD_SETSIZE)
                printf("client link too many\n");
            /*  std::cout << "client link too many\n";*/

            FD_SET(clientfd, &allset);
            if(i > maxi){
                maxi = i;
            }
            if(clientfd > maxfd){
                maxfd = clientfd;
            }
            if(--readnum <= 0) continue;
        }

        for(i = 0; i <= maxi; ++i){
            if(client[i] != -1 && FD_ISSET(client[i], &rset)){
                sockfd = client[i];
                if((n = Readline(sockfd, recvbuf, MAXLINE)) == 0){
                    FD_CLR(sockfd, &allset);
                    Close(sockfd);
                    client[i] = -1;
                } else{
                    Write(sockfd, recvbuf, n);
                }

                if(--readnum <= 0) break;
            }
        }
    }

    return 0;
}

1.首先的初始化监听套接字描述符,把fd_set中对应的套接字描述符,设置为1,然后进入监听程序,当有新的cilent连接的时候,select监听的套接字描述符将会变成可读的状态,然后进入可读程序。

2.Select函数中第2-4个参数,都是属于值-结果类型,最后一个参数为NULL, Select函数将会永远堵塞于改程序处,除非遇到捕捉到系统信号,而中断并且errno置于EINTR,又或者是某个描述符变成可读状态

3.第34行都51行的代码,首先检查client数组中最低位为-1的位置,将其已经连接的套接字描述符记录下来。然后检查更新maxi和最大的套接字描述符。

过程如下所示



4.第55行到66行的代码,对来至client发送的信息进行处理,首先我们对每个fd进行检验(先检查,该位置是否有连接,然后通过调用FD_ISSET函数进行检验该套接字描述符是否可读),如果读到的数据等于0.那么则表示收到了来之client的FIN分节,则选择将该描述符从fd_set结构中取出,然后关闭套接字描述符,同时把client中该套接字描述符对应位置上面的值置为-1.


5.在全过程还有一个不容忽略的值就是readnum,他表示fd_set结构中,可读的描述符号的数量,每次处理完一个对应的描述符过后都必须对其进行--操作



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值