linux下使用select I/O複用和多線程編程實現簡單的TCP服務器

    I/O複用之Select模型
編程

I/O複用使得程序可以同時監聽多個文件描述符,可是,他自己也是阻塞的,而且當一個或多個文件描述符準備就緒時,若是不採用其餘措施,程序只能按順序處理其中的每一個文件描述符。若是要使程序可以並行運行,只能使用多進程或多線程的方式。數組

Linux下實現I/O複用的系統調用主要有select、poll和epoll,下面將詳細介紹select的系統調用。服務器

Select系統調用的用途:在一段時間內,監聽用戶感興趣的文件描述符上面的可讀、可寫和異常等事件。數據結構

相關API的介紹:多線程

#include <sys/select.h>
int select(int nfds, fd_set * readfds, fd_set * writefdds, fd_set * exceptfds, struct timeval * timeout);

nfds參數:全部監聽的文件描述符的最大值 + 1socket

readfds、writefds和exceptfds參數分別爲可讀、可寫和異常等事件對應的文件描述符集合;程序只須要傳入本身感興趣的文件描述符,內核將修改他們來通知程序那些文件描述符已經準備就緒;fd_set結構體僅包含一個整形數組,該數組的每個元素的每一位標誌一個文件描述符,下面的一組宏用來操做fd_set的每一位:測試

FD_ZERO(fd_set * fdset);//清除fd_set的全部位
FD_SET(int fd, fd_set * fdset);//設置fdset的位fd
FD_CLR(int fd, fd_set * fdset);//清除fdset的位fd
int FD_ISSET(int fd, fd_set * fdset);//測試fdset的位fd是否被設置

ttimeout參數:timeout參數是一個timeval結構體,timeval的結構體的定義以下spa

struct timeval
{
long tv_sec;//秒數
long tv_usec;//微秒數
};

若是tv_sec和tv_usec都設置爲0,則select當即返回, 若是timeout參數設置爲NULL,則select一直阻塞直到某個文件描述符準備就緒。.net

返回值:成功返回就緒的文件描述符的總數,若是超過期間內沒有任何文件描述符準備就緒,select將返回0,失敗則返回-1並設置errno;若在select等待事件內程序接收到信號,則select當即返回-1,並設置errno爲EINTER。線程

文件描述符的就緒條件:

可讀描述符就緒條件:

接收緩衝區中的字節數大於或等於SO_RCVLOWAT標誌

有新的鏈接請求

ƒ對方關閉鏈接

有未處理的錯誤

可寫描述符的就緒條件:

發送緩衝區中的可用字節數大於或等於SO_SENLOWAT標誌

寫操做被關閉

ƒ有未處理的錯誤

異常文件描述符的就緒條件:

socket上接收帶外數據


代碼示例:

http://www.oschina.net/code/snippet_861360_27324

分享的代碼主要是使用select系統調用和多線程編程實現一個簡單的並行的TCP服務器

select 模型的有缺點:

優勢:select模型的優勢之一就是良好的跨平臺支持

缺點:

1、單個進程可以監測的文件描述符有限,通常爲1024,能夠經過修改內核修改

2、select維護了存儲大量文件描述符的數據結構,隨着文件描述符的增長,其複製的開銷及遍歷形成的開銷影響系統效率。

相關文章
相關標籤/搜索