如何使用epoll 乙個C語言的簡單例子

2021-08-26 19:49:17 字數 3687 閱讀 4539

* how to use epoll? a complete example in c 譯文

通常的網路伺服器實現, 是對每乙個連線使用乙個單獨的執行緒或程序。對高效能應用而言,由於需要同時處理非常多的客戶請求, 所以這種方式並不能工作得很好,因為諸如資源使用和上下文切換所需的時間影響了在一時間內對多個客戶端進行處理。另乙個可選的途徑是在乙個單獨的執行緒裡採用非阻塞的i/o, 這樣當可以從乙個socket中讀取或寫入更多資料時,由一些已經準備就緒的通知方式來告知我們。

這篇文章介紹linux 的 epoll方法, 它是linux上最好的就緒通知方式。我們會寫乙個用c語言的tcp伺服器的完全實現的簡單程式。假設你已有c程式設計的經驗,知道在linux 下編譯和執行程式, 並且會用 manpages 來檢視所使用的 c 函式。

epoll 是在 linux 2.6 才引進的,而且它並不適用於其它 unix-like 系統。它提供了乙個與select 和 poll 函式相似的功能:

+ select 可以在某一時間監視最大達到 fd_setsize 數量的檔案描述符, 通常是由在 libc 編譯時指定的乙個比較小的數字。

+ poll 在同一時間能夠監視的檔案描述符數量並沒有受到限制,即使除了其它因素,更加的是我們必須在每一次都掃瞄所有通過的描述符來檢查其是否存在己就緒通知,它的時間複雜度為 o(n) ,是緩慢的。

epoll 沒有以上所示的限制,並且不用執行線性掃瞄。因此, 它能有更高的執行效率且可以處理大數量的事件。

當描述符被新增到epoll例項中, 有兩種新增模式: level triggered(級別觸發) 和 edge triggered(邊沿觸發) 。 當使用 level triggered 模式並且資料就緒待讀, epoll_wait總是會返加就緒事件。如果你沒有將資料讀取完, 並且呼叫epoll_wait 在epoll 例項上再次監聽這個描述符, 由於還有資料是可讀的,它會再次返回。在 edge triggered 模式時, 你只會得一次就緒通知。 如果你沒有瘵資料讀完, 並且再次在 epoll例項上呼叫 epoll_wait , 由於就緒事件已經被傳送所以它會阻塞。

傳遞到 epoll_ctl 的epoll事件結構體如下所示。對每乙個被監聽的描述符,你可以關聯到乙個整數或乙個作為使用者資料的指標。

typedef union epoll_data

epoll_data_t;

struct epoll_event

;

馬上實踐寫**。我們會實現乙個小的tcp伺服器,它會將所有socket上收到的資料輸出到標準輸出。 首先寫乙個 create_and_bind() 函式,它建立並繫結乙個tcp socket.

static int

create_and_bind (char *port)

for (rp = result; rp != null; rp = rp->ai_next)

close (sfd);

}if (rp == null)

freeaddrinfo (result);

return sfd;

}

create_and_bind函式包含了一種可移植方式來獲取ipv4或ipv6套接字的標準**段。它接受乙個port的字串引數,port是從argv\[1\]中傳入的。其中,getaddrinfo函式返回一群addrinfo到result,其中它們跟傳入的hints引數是相容的。 addrinfo結構體如下:

struct addrinfo

;

我們依次遍歷這些結構體並用其來建立結構體,直到我們可以同時建立和繫結到socket。如果我們成功,create_and_bind() 會返回乙個socket描述符。失敗則返回 -1.

接下來,我們寫乙個用來設定socket為非阻塞的函式。 make_socket_non_blocking() 設定 o_nonblock 標誌給傳入的sfd描述符引數。

static int

make_socket_non_blocking (int sfd)

flags |= o_nonblock;

s = fcntl (sfd, f_setfl, flags);

if (s == -1)

return 0;

}

接下來的main()函式中,它包含有乙個事件迴圈。 下面是**:

#define maxevents 64

intmain (int argc, char *argv)

sfd = create_and_bind (argv[1]);

if (sfd == -1)

abort ();

s = make_socket_non_blocking (sfd);

if (s == -1)

abort ();

s = listen (sfd, somaxconn);

if (s == -1)

efd = epoll_create1 (0);

if (efd == -1)

event.data.fd = sfd;

event.events = epollin | epollet;

s = epoll_ctl (efd, epoll_ctl_add, sfd, &event);

if (s == -1)

/* buffer where events are returned */

events = calloc (maxevents, sizeof event);

/* the event loop */

while (1)

else if (sfd == events[i].data.fd)

else

}s = getnameinfo (&in_addr, in_len,

hbuf, sizeof hbuf,

sbuf, sizeof sbuf,

ni_numerichost | ni_numericserv);

if (s == 0)

/* make the incoming socket non-blocking and add it to the

list of fds to monitor. */

s = make_socket_non_blocking (infd);

if (s == -1)

abort ();

event.data.fd = infd;

event.events = epollin | epollet;

s = epoll_ctl (efd, epoll_ctl_add, infd, &event);

if (s == -1)

}continue;

}else

break;

}else if (count == 0)

/* write the buffer to standard output */

s = write (1, buf, count);

if (s == -1)

}if (done)}}

}free (events);

close (sfd);

return exit_success;

}

關於main函式裡就不多說了。

乙個sample學會使用epoll

include include include include include include include include include include include include define max event number 1024 define tcp buffer size 51...

如何使用C語言實現乙個簡單的字典

題目要求 實現簡單的英漢詞典,詞庫就10個單詞好了 實現功能 輸入單詞時,可以輸出相應的中文 輸入中文時,可以輸出相應的英文 如果輸入的單詞或者中文查詢不存在時,則輸出 你所查詢的內容不存在,請重新輸入 要求使用鍊錶來實現,並且直至輸入能查詢的詞時程式才退出,只要查詢不到就要一直重複輸入 提供10個...

如何構造乙個C 語言的爬蟲程式

c 特別適合於構造蜘蛛程式,這是因為它已經內建了http訪問和多執行緒的能力,而這兩種能力對於蜘蛛程式來說都是非常關鍵的。下面是構造乙個蜘蛛程式要解決的關鍵問題 html分析 需要某種html解析器來分析蜘蛛程式遇到的每乙個頁面。頁面處理 需要處理每乙個儲存到磁碟,或者進一步分析處理。多執行緒 只有...