Linux網路程式設計之多路I O復用

2021-10-25 15:22:31 字數 2745 閱讀 8245

1. select函式

#include

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

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);

參1:最大的檔案描述符 + 1

2. poll函式

#include

int poll(struct pollfd* fds, nfds_t nfds, int timeout);

struct pollfd epoll_data_t;

int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);

events: 陣列,傳出引數。

maxevents:告知核心這個events有多大

timeout: 超時時間, -1 --> 阻塞; 0 --> 立即返回,非阻塞;> 0 --> 指定毫秒

返回值:成功返回有多少檔案描述符就緒,時間到時返回0,出錯返回-1.

#ifndef _multithread_epoll_test_h

#define _multithread_epoll_test_h

class epollserver

;#endif

#include #include #include #include #include #include #include #include #include #include #include #include "multithread_epoll_test.h"

epollserver::epollserver()

epollserver::~epollserver()

void epollserver::onrun()

for (int i = 0; i < ret; ++i)}}

}void epollserver::accept()

char buf[bufsiz];

printf("new client joined, port = %d, ip = %s\n",

ntohs(clientaddr.sin_port),

inet_ntop(af_inet, (const void*)&clientaddr.sin_addr.s_addr, buf, bufsiz));

struct epoll_event evt;

bzero(&evt, sizeof(evt));

evt.events = epollin;

evt.data.fd = clientfd;

epoll_ctl(m_epfd, epoll_ctl_add, clientfd, &evt);

}void epollserver::handlemsg(int clientfd)

else if (ret < 0)

else

}

4. 水平觸發epoll lt/ 邊沿觸發 epoll et

水平觸發:evt.events = epollin; --> 預設

邊沿觸發:  evt.events =epollin | epollet;

5. 非阻塞i/o: fcntl函式與open函式(open不適用socket)

int flag = fcntl(cfd, f_getfl);

flag |= o_nonblock;

fcntl(cfd, f_setfl, flag);

非阻塞模式read時需要while迴圈,從而達到減少epoll_wait的呼叫。

邊沿觸發 + 非阻塞模式是最高效的方式。邊沿觸發在一次性讀不完資料時可以減少epoll_wait的呼叫。

epoll工作在et模式的時候,必須使用非阻塞套介面,以避免由於乙個檔案控制代碼的阻塞讀/阻塞寫操作把處理多個檔案描述符的任務餓死。最好以下面的方式呼叫et模式的epoll介面,在後面會介紹避免可能的缺陷。

i    基於非阻塞檔案控制代碼

ii   只有當read(2)或者write(2)返回eagain時才需要掛起,等待。但這並不是說每次read()時都需要迴圈讀,直到讀到產生乙個eagain才認為此次事件處理完成,當read()返回的讀到的資料長度小於請求的資料長度時,就可以確定此時緩衝中已沒有資料了,也就可以認為此事讀事件已處理完成。

所以判斷et模式迴圈讀取是否讀取完成的方法:當讀取資料長度小於設定的長度或者返回-1並且errno為eagain或ewouldblock時。

當讀取數量==請求數量時,繼續讀取下一輪(buffer太小)。

while (1)

close(sockfd);

break;

}else if (ret == 0)

else

printf("收到訊息:%s, 共%d個位元組\n", buffer, ret);

}printf("帶迴圈的et處理結束!!!\n");

網路程式設計之 多路IO轉接 select模型

select模型 優點 可跨平台 實現多路復用 避免了頻繁建立多程序 多執行緒處理連線產生的開銷,提高了連線處理效率 缺點 最多監聽1024個檔案描述符 事件處理時需要依次遍歷,帶來不必要的開銷 select函式原型 nfds 最大描述符加1 readfds 輸入輸出引數 返回讀事件檔案描述符集合 ...

網路程式設計之 多路IO轉接 select模型改進

select模型中在處理監聽事件時需要對檔案描述符依次遍歷,此處可以稍作改進,避免不必要的遍歷。改進思路 定義乙個fd setsize大小的陣列,用於儲存有效連線 定義乙個下標變數用於記錄儲存連線陣列中的有效連線最大下標,供遍歷作為上限值使用 int maxc 1 int client fd set...

網路程式設計之沒有io多路復用

網路程式設計www.baidu.com 網域名稱 每個網域名稱都有對應的ip 202.108.22.5 tcp 有連線的,可靠的,一定可以保證訊息可以傳達給對方,有三次握手 udp 沒有連線到 不可靠的 不能保證訊息一定能夠傳達給對方,不存在三次握手 利用套接字進行通訊 伺服器有兩個套接字 乙個叫監...