以前咱們使用了幾種服務器模型,一個是單進程的, 同一時候只能給一個客戶端提供服務, 後來咱們使用了多進程, 每一個客戶端fork新進程進行業務處理bash
IO多路複用是指內核一旦發現進程指定的一個或者多個IO條件準備讀取,它就通知該進程,能夠使用一個進程服務多個客戶端.服務器
select函數原型:函數
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set * readset, fd_set * writeset, fd_set * exceptset, const struct timeval * timeout);
成功時返回大於0的值, 失敗時返回 -1
複製代碼
參數解釋:ui
maxfd 監視對象文件描述符的數量,舉例寫法 sever_sock+1
readset 存儲的待讀取數據文件描述符
writeset 可傳輸無阻塞數據文件描述符
exceptset 發生異常的文件描述符
timeout 超時設置
複製代碼
select函數返回值, 若是返回大於0的整數, 說明相應數量的文件描述符發生了變化.spa
咱們發如今 參數類型上有 fd_set類型,這是什麼類型呢? 咱們設置的文件描述符對應的位存儲數據格式, 咱們設置這些文件描述符對應位時, 能夠使用一些宏實現3d
FD_ZERO(fd_set * fdset)
將 fd_set 變量的全部位初始化位0
FD_SET(int fd, fd_set * fdset)
在參數 fd_set 指向的變量中註冊文件描述符 fd 的信息
FD_CLR(int fd, fd_set * fdset)
從參數 fdset 指向的變量中清除文件描述符 fd 的信息
FD_ISSET(int fd, fd_set * fdset)
若參數 fdset 指向的變量中包含文件描述符 fd 的信息,則返回真
複製代碼
struct timeval
{
long tv_sec; //seconds
long tv_usec; //microseconds
}
複製代碼
select.ccode
#include <stdio.h>
#include <sys/select.h>
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
//監視的文件描述符
fd_set reads, temps;
struct timeval timeout;
int result, str_len;
char buf[BUF_SIZE];
FD_ZERO(&reads);
FD_SET(0, &reads); //0 is standard input(console)
while (1)
{
//由於每次select會重置監控句柄,因此賦值給臨時
temps = reads;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// puts 只有事件發生或者發生超時才執行,不然select阻塞
puts("xxxx");
result = select(1, &temps, 0, 0, &timeout);
if (result == -1)
{
puts("select() error");
}
else if (result == 0)
{
puts("nothing event change..time out");
}
else
{
if (FD_ISSET(0, &temps))
{
str_len = read(0, buf, BUF_SIZE);
printf("message from consle: %s\n", buf);
}
}
}
}
複製代碼
gcc select.c -o select
./select
xxxx
123456
message from consle: 123456
xxxx
7890ha
message from consle: 7890ha
xxxx
nothing event change..time out
xxxx
777
message from consle: 777
xxxx
^C
複製代碼