在unix/c中,socket相關的函式操作都是阻塞式的,在單執行緒下服務端只能處理乙個客戶端請求。採用多執行緒處理客戶端請求,雖然能充分發揮多核cpu能力,但是在客戶端連線過多,併發度維持相對較高水平時,多執行緒引起執行緒的上下文切換將導致系統效率低下。select多路復用模型的核心思想,在單執行緒下處理多客戶端連線,unix/c提供了相應函式庫,具體如下:
int select (int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
const struct timeval* timeout);
struct timeval ;
fd_set是乙個socket鍊錶,以下巨集可以對該佇列進行操作:
fd_clr( s, *set) 從佇列set刪除控制代碼s;
fd_isset( s, *set) 檢查控制代碼s是否存在與佇列set中;
fd_set( s, *set )把控制代碼s新增到佇列set中;
fd_zero( *set ) 把set佇列初始化成空佇列.
select執行流程:
1:用fd_zero巨集來初始化我們感興趣的fd_set。
2:用fd_set巨集來將套接字控制代碼分配給相應的fd_set。
3:呼叫select函式
4:用fd_isset對套接字控制代碼進行檢查。
服務端**如下:
#include
#include
#include
#include
#include
#include
#include
#include
#define port 8080
#define backlog 1024
#define bufsize 64
int client_count;
int main()
int select_ret = -1;
if((select_ret = select(max_fd+1, &socket_fd, null, null, &tik)) < 0)
if(select_ret == 0)
continue;
for(index = 0;index < client_count;index++)
if(fd_isset(fds[index], &socket_fd))
read_handler(&fds[index]);//處理io事件
if(fd_isset(server_socket, &socket_fd))
connect_handler(server_socket, fds + client_count);//處理連線
}return0;}
char *get_client_info(int client_fd)
void read_handler(int *socket_fd)else
if(len == 0 )else
}void connect_handler(int server_socket, int *fd)else
}int create_socket(struct sockaddr_in socket_addr, int backlog)
int on = 1;
setsockopt(server_socket, sol_socket, so_reuseaddr, &on, sizeof(on));
int bind_ret = -1;
if((bind_ret = bind(server_socket, &socket_addr, sizeof(socket_addr)))<0)
int listen_ret = -1;
if((listen_ret = listen(server_socket, backlog))<0)
return server_socket;
}
客戶端**:
#include
#include
#include
#include
#include
#define port 8080
int main()
connect(socket_fd, &client_addr, sizeof(client_addr));
char send_buf[64],recv_buf[64];
memset(send_buf, 0, sizeof(send_buf));
memset(recv_buf, 0, sizeof(recv_buf));
while(fgets(send_buf,sizeof(send_buf),stdin)!=null)
close(socket_fd);
return
0;}
執行效果如下圖:
小結:select模型解決了單執行緒下,無法處理多客戶端請求問題。但由於其採用輪詢策略依次去處理所有socket控制代碼,而通常大多數連線處理不活躍狀態,這導致輪詢效率低下;實驗表明,在大部分客戶端不活躍而維持長連線狀態時,select多路復用模型的效率並不比多執行緒分別處理客戶端效率高。此外,由於select基於檔案描述符實現多路復用,其最大併發處理的併發數也受到作業系統相應的限制(linux預設1024)。
多路復用IO模型之select
多路i o復用表示支援多個任務同時對某一程序的i o程序操作,普通的read write只能實現同一時間操作乙個,無法實現網路通訊的併發操作。那麼多路復用i o分為三種機制 select poll epoll 1.占用記憶體多 2.程序 執行緒 切換時間多。3.程序 執行緒 之間同步麻煩 在主控執行...
IO多路復用 select模型
客戶端 見 c s通訊 伺服器阻塞型使用 伺服器端 include include include include include include include include include include include include int main set local address m...
IO多路復用 select
select系統呼叫的目的是 在一段指定時間內,監聽使用者感興趣的檔案描述符上的可讀 可寫和異常事件。poll和select應該被歸類為這樣的系統 呼叫,它們可以阻塞地同時探測一組支援非阻塞的io裝置,直至某乙個裝置觸發了事件或者超過了指定的等待時間 也就是說它們的職責不是做io,而是幫助 呼叫者尋...