select-IO多重化

15628 ワード

1、基本概念IO多重化とは、カーネルがプロセスによって指定された1つまたは複数のIO条件が読み取りの準備をしていることを発見すると、そのプロセスに通知することである.IO多重化は以下の場合に適用される.
  • お客様が複数の記述語を処理する場合(一般的にはインタラクティブ入力およびネットワークソケットインタフェース)、I/O多重化を使用する必要があります.
  • は、1つのクライアントが複数のインタフェースを同時に処理する場合、このような状況は可能であるが、めったに発生しない.
  • TCPサーバがリスニング・スイート・インタフェースと接続されたスイート・インタフェースの両方を処理する場合、I/O多重化も一般的に使用されます.
  • サーバがTCPを処理し、UDPも処理する場合、I/O多重化が一般的に使用されます.
  • サーバが複数のサービスまたは複数のプロトコルを処理する場合、I/O多重化
  • が一般的に使用されます.
    マルチプロセスとマルチスレッド技術と比較して、I/O多重技術の最大の利点はシステムオーバーヘッドが小さく、システムがプロセス/スレッドを作成する必要がなく、これらのプロセス/スレッドを維持する必要がなく、システムのオーバーヘッドを大幅に削減することである.2、select関数プロセスは、カーネルが複数のイベントのいずれかの送信を待機し、1つ以上のイベントが発生したか、または指定された時間が経過した後にのみ起動することを示す.関数のプロトタイプは次のとおりです.
    #include 
    #include 

    int select(int maxfdp 1,fd_set*readset,fd_set*writeset,fd_set*exceptset,const struct timeval*timeout)戻り値:準備記述子の数、タイムアウト戻り0、エラー戻り-1
    関数パラメータの説明は次のとおりです.
  • 最初のパラメータmaxfdp 1は、テスト対象の記述ワード数を指定し、その値はテスト対象の最大記述ワードプラス1(したがって、このパラメータをmaxfdp 1と命名する)、記述ワード0、1、2...maxfdp 1-1がテストされる.ファイル記述子は0から始まるからです.
  • の3つのパラメータreadset、writeset、exceptsetは、カーネルに読み取り、書き込み、および異常条件をテストさせる記述語を指定します.ある条件に興味がなければ、空のポインタに設定できます.struct fd_setは、ファイル記述子が格納された集合として理解することができ、
  • は、以下の4つのマクロによって設定することができる.
    void FD_ZERO(fd_set *fdset);           //    
    void FD_SET(int fd, fd_set *fdset);   //                 
    void FD_CLR(int fd, fd_set *fdset);   //                 
    int FD_ISSET(int fd, fd_set *fdset);   //                     
  • timeoutは、指定された記述ワードのいずれかの準備がどれだけ時間がかかるかをカーネルに通知する.そのtimeval構造は、この時間の秒数とマイクロ秒数を指定するために使用されます.struct timeval{ long tv_sec;//seconds long tv_usec;//microseconds };

  • このパラメータには,(1)I/Oの準備ができている記述語が1つある場合にのみ戻る,(3)常に待つ可能性がある.このため、このパラメータを空ポインタNULLに設定します.(2)一定時間待機:記述語がI/Oの準備ができているときに戻るが、このパラメータによって指定されたtimeval構造で指定された秒数とマイクロ秒数を超えない.(3)まったく待たない:記述語をチェックしてすぐに戻ることをポーリングと呼ぶ.このため、パラメータはtimeval構造を指し、タイマ値は0でなければなりません.
    次は私が書いたselectのdemoで、後で使うか、みんなが必要とするようにします.
    /*********************************************************
    -  Copyright (C): 2016
    -  File name    : server.c
    -  Author       : - Zhaoxinan -
    -  Date         : 2016 09 29      15 09 06 
    -  Description  :    selcetIO    
    
    *  *******************************************************/
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    //   8000
    #define PORT 8000
    //     80
    #define MAX_LINE 80
    
    int main()
    {
        int i;
        int ret;
        int sockfd;
        int new_fd;
        int work_fd;
        int sin_size;
        int opt = 1;
    
        int maxi;
        int maxfd;
    
        fd_set readset;
        fd_set allset;  
    
        int client[FD_SETSIZE]; //              
    
        char buffer[MAX_LINE];
    
        socklen_t addr_len; //      
    
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;
    
        //    TCP   
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            fprintf(stderr, "Socket error!
    "
    , strerror(errno)); exit(1); } // bzero(&server_addr, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); // 30s setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // IP if (bind(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1) { fprintf(stderr, "Bind error:%s
    \a"
    , strerror(errno)); exit(1); } printf("bind
    "
    ); // if (listen(sockfd, 30) == -1) { fprintf(stderr, "Listen error:%s
    \a"
    , strerror(errno)); exit(1); } printf("listening!
    "
    ); // maxfd = sockfd; maxi = -1; for (i = 0; i < FD_SETSIZE; i++) { client[i] = -1; } // FD_ZERO(&allset); // sockfd FD_SET(sockfd, &allset); while (1) { readset = allset; // ret = select(maxfd + 1, &readset, NULL, NULL, NULL); if (ret == -1) { printf("select error!
    "
    ); exit(1); } // sockfd if (FD_ISSET(sockfd, &readset)) { // if client_fd addr_len = sizeof(server_addr); if ((new_fd = accept(sockfd, (struct sockaddr*)(&client_addr), &addr_len)) == -1) { fprintf(stderr, "Accept error:%s
    \a"
    , strerror(errno)); exit(1); } printf("accept
    "
    ); printf(" fd = %d
    "
    , new_fd); // newfd // for (i = 0; i < FD_SETSIZE; i++) { if (client[i] <= 0) { client[i] = new_fd; break; } } // , if (i == FD_SETSIZE) { printf("too many clients
    "
    ); exit(1); } // FD_SET(new_fd, &allset); if (new_fd > maxfd) { maxfd = new_fd; } if (i > maxi) { maxi = i; } } // for (i = 0; i < FD_SETSIZE; i++) { if ((work_fd = client[i]) < 0) { continue; } // fd , if if (FD_ISSET(work_fd, &readset)) { printf("reading
    "
    ); ret = read(work_fd, buffer, MAX_LINE); if (ret == 0) { // printf("the other side has been close
    "
    ); fflush(stdout); close(work_fd); // FD_CLR(work_fd, &allset); client[i] = -1; } else { printf(" fd = %d
    "
    , work_fd); printf("%s
    "
    , buffer); printf("__________________
    "
    ); printf("readok!
    "
    ); } } } } close(sockfd); return 0; }
    /*********************************************************
    -  Copyright (C): 2016
    -  File name    : client.c
    -  Author       : - Zhaoxinan -
    -  Date         : 2016 10 07      22 03 58 
    -  Description  : IO       
    
    *  *******************************************************/
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define PORT 8000
    
    int main(int argc, char **argv)
    {
        int ret;
        int sockfd;
        int n_write;
    
        char buffer[80];
    
        struct sockaddr_in server_addr;
    
        if (argc != 2)
        {
            exit(1);
        }
    
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            exit(1);
        }
    
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(PORT);
        server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    
        if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
        {
            exit(1);
        }
    
        while (1)
        {
            memset(buffer, 0, sizeof(buffer));
            scanf("%s", buffer);
    
            n_write = write(sockfd, buffer, sizeof(buffer));
            if (n_write == -1)
            {
                printf("write error!
    "
    ); } printf("_________________
    "
    ); } return 0; }