對 linux socket select的淺顯理解

對linux socket 通信的多路複用模型select談談我的理解。

socket通信服務器端程序流程:

socket(AF_INET,SOCK_STREAM,0);

setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&I,sizeof(I));

該函數可以解決編譯器報的:address already in use  的錯誤。

bind(sock_fd,(struct sockaadr*)&server_addr,sizeof(server_addr));

listen(sock_fd,connect_count);

accept(sock_fd,(struct sockaddr*)&client_addr,sizeof(client_addr));

過後就是read ,write函數對客戶端的所發的數據進行讀取。

以上就是普通服務器端程序的基本流程,但是客戶端與服務器段程序的通信並不是一對一的,一個服務器可能有多個客戶端同時連接,爲了解決這類併發問題,我們可以採用多進程,多線程方式,同樣,多路複用:select也可以解決這個問題。

select的缺點:select最多隻能支持添加1024個文件描述符,並且當文件描述符添加多了過後,select函數的效率會大幅下降,因爲我們添加fd和使用這個select函數都會遍歷一遍數組,無論是該fd是否是我們需要的那個。但是select還是比多進程多線程要高效。

 

NAME
       select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing


    
       #include <sys/select.h>

       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

第一個參數:最大的文件描述符+1;

第二個參數:讀的字符集;

第三個參數:寫的字符集;不需要時可以設置爲NULL;

第四個參數:錯誤的字符集;不需要時可以設置爲NULL;

第五個:struct timeval *timeout:當select等待時間超過時間限度就繼續等待,可以設置爲NULL,用不超時。

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

通過man select 可以查看該函數,以及以上對fd的一系列操作函數。

FD_CLR:用於刪除文件描述符集合中一個一個文件描述符。

FD_ISSET:判斷這個文件描述符是否存在於該文件描述符集中。

FD_SET:將這文件描述符添加到該文件描述符集中。

FD_ZERO:將文件描述符集清零。

大概流程:

fd_set readfds;創建讀的字符集;

。。。

。。。

。。。

acceptfd=accept(sock_fd,(struct sockaddr*)&client_addr,sizeof(client_addr));

一個while循環

while(1)

{

     FD_ZERO(&readfds);對該字符集進行清零
     FD_SET(0,&readfds);
     maxfd=0;將maxfd設置爲readfds中的d一個。

    ret = select(maxfd+1,&readfds,NULL,NULL,&tv);

    select函數ret 返回值 < 0 ,select創建失敗,返回值ret== 0,等待超時;

   if(FD_ISSET(0,&readfds))

  {

        memset(buf,0,maxbuf+1);對buf清理buff;

        fgets(buf,maxbuf,stdin);從標準輸入中讀取數據到buf中,

 

    }

if(FD_ISSET(acceptfd,&readfds))

判斷acceptfd是否存在於readfds;

{

    bzero(buf,maxbuf+1);清理buf

    len=recv(acceptfd,buf,maxbuf,0);從acceptfd描述符中接收數據,當返回值<=0時,未能從描述符zh中讀取到數據。

}

close(acceptfd);關閉文件描述符。

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章