伺服器呼叫select函式檢測兩種不同型別的輸入事件
1、新的客戶端請求到達,此時監聽描述符準備好可以讀了
伺服器開啟連線並將該客戶新增到池裡
2、乙個已存在的客戶端的已連線描述符準備好可以讀了
伺服器把來自每個已經準備好的已連線描述符的乙個文字行回送回去
(當且僅當乙個從該描述符讀取乙個位元組的請求不會阻塞,描述符k就表示準備好可以讀了)
#include
#include
#include
#include
#include
//robust io
ssize_t rio_writen(int fd, void *userbuf, size_t n)
nleft -= nwrite;
bufp += nwrite;
}return n;
}//帶快取版本
static
const
int rio_bufsize = 8192;
struct rio_t
;void rio_readinitb(rio_t *rp, int fd)
ssize_t rio_read(rio_t *rp, void *userbuf, size_t n)
else
if (rp->rio_cnt == 0)
return
0; else
rp->rio_bufptr = rp->rio_buf;
}size_t cnt = n > rp->rio_cnt ? rp->rio_cnt : n;
memcpy(userbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;
}//讀文字行,複製到記憶體位置userbuf,最後在結尾添null(0)
ssize_t rio_readlineb(rio_t *rp, void *userbuf, size_t maxlen)
else}}
*buf = 0;
return i-1;
}//開啟監聽描述符
int open_listenfd(const
char *port)
freeaddrinfo(listp);
if(!p)
return -1;
if(listen(listenfd, 3) < 0)
return listenfd;
}int maxline = 100;
struct pool
;void init_pool(int listenfd, pool *p)
//剛開始只有監聽描述符
p->maxfd = listenfd;
fd_zero(&(p->read_set));
fd_set(listenfd,&(p->read_set));
}void add_client(int connfd, pool *p)
//陣列已經滿了,fd_setsize為1024
if(i == fd_setsize)
perror("add_client error: too many clients");
}}//伺服器接收的總位元組數
int byte_cnt = 0;
void check_clients(pool * p)
else
//已經從客戶端讀完文字行,檢測到eof,關閉連線}}
}int main(int argc, const
char * argv)
listenfd = open_listenfd(argv[1]); //開啟監聽描述符,argv[1]為埠號,這裡選擇8000
init_pool(listenfd, &pool);
while(1)
check_clients(&pool);
}}
I O多路復用
一 五種i o模型 1 阻塞i o模型 最流行的i o模型是阻塞i o模型,預設情形下,所有套介面都是阻塞的。我們以資料報套介面為例來講解此模型 我們使用udp而不是tcp作為例子的原因在於就udp而言,資料準備好讀取的概念比較簡單 要麼整個資料報已經收到,要麼還沒有。然而對於tcp來說,諸如套介面...
i o多路復用
最常見的i o多路復用就是 select poll epoll了,下面說說他們的一些特點和區別吧。select 可讀 可寫 異常三種檔案描述符集的申明和初始化。fd set readfds,writefds,exceptionfds fd zero readfds fd zero writefds ...
I O多路復用
我們都知道unix like 世界裡,一切皆檔案,而檔案是什麼呢?檔案就是一串二進位製流而已,不管socket,還是fifo 管道 終端,對我們來說,一切都是檔案,一切都是流。在資訊 交換的過程中,我們都是對這些流進行資料的收發操作,簡稱為i o操作 input and output 往流中讀出資料...