學習Linux C-網絡調用:select

學習Linux c,首先需要寫的是一個基於tcp的網絡調用server,下面逐個註釋分析代碼邏輯。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define SERV_PORT 6677
#define LENGTH_OF_LISTEN_QUEUE  20
#define MAXLINE 100

int main(int argc, char **argv)
{
    int i,maxi,maxfd,listenfd,connfd,sockfd;
    int nready,client[FD_SETSIZE];

    /* 
    /usr/include/sys/types.h 
    */
    ssize_t n; 

    /*
    /usr/include/sys/select.h
    可以理解爲一個集合,這個集合中存放的是文件描述符(filedescriptor),即文件句柄,這可以是我們所說的普通意義的文件,當然Unix下任何設備、管道、FIFO等都是文件形式,全部包括在內,所以毫無疑問一個socket就是一個文件,socket句柄就是一個文件描述符
    */
    fd_set rset, allset;
    char buf[MAXLINE];

    /*
    /usr/include/netinet/in.h
    */
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;

    /*
    /usr/include/sys/socket.h
    */
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if( listenfd < 0 )
    {
        printf("create socket failed!\n");
        exit(1);
    }

    /*
    /usr/include/strings.h
    */
    bzero(&servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    {
        printf("server bind port %d failed!\n", SERV_PORT);
        exit(1);
    }

    if(listen(listenfd, LENGTH_OF_LISTEN_QUEUE))
    {
        printf("Server Listen Failed!\n");
                exit(1);
    }

    maxfd = listenfd;
    maxi = -1;

    for(i = 0; i < FD_SETSIZE; i++)
        client[i] = -1;

    FD_ZERO(&allset);
    FD_SET(listenfd, &allset);

    for(;;)
    {
        rset = allset;
        /*
        負值:select錯誤 正值:某些文件可讀寫或出錯 0:等待超時,沒有可讀寫或錯誤的文件
        */
        nready = select(maxfd+1, &rset , NULL , NULL, NULL);
        //printf("nready:%d\n", nready);
        printf("maxfd:%d\n", maxfd);

        if(FD_ISSET(listenfd, &rset))
        {
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

            for(i = 0; i< FD_SETSIZE; i++)
            {
                if(client[i] < 0){
                    client[i] = connfd;
                    break;
                }
            }

            if (i == FD_SETSIZE)
            {
                printf("too many clients\n");
                exit(1);
            }
            FD_SET(connfd, &allset);

            if(connfd > maxfd)
                /* int maxfd是一個整數值,是指集合中所有文件描述符的範圍,即所有文件描述符的最大值加1 */
                maxfd=connfd;

            if(i > maxi)
                maxi = i;

            if(--nready <= 0)
                continue;

        }

        for (i = 0; i<=maxi; i++)
        {
            if((sockfd = client[i]) < 0)
                continue;

            if(FD_ISSET(sockfd, &rset))
            {
                /*從socket讀取內容*/
                if((n = read(sockfd, buf, MAXLINE)) == 0)
                {
                    close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client[i] = -1;
                }else
                {
                    /*把內容寫入socket*/
                    write(sockfd, buf, n);
                }

                if( --nready <= 0 )
                    break;
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章