導航:首頁 > 文件教程 > epoll頭文件

epoll頭文件

發布時間:2023-03-08 03:21:53

linux epoll是只針對網路編程嗎

對於改進poll的epoll來說:支持一個進程打開大數目的socket描述符,也就是說與本機的內存是有關系的!( 一般伺服器的都是很大的! )
下面是我的小PC機上的顯示:
pt@ubuntu:~$ cat /proc/sys/fs/file-max
391658
達到了391658個,那麼對於伺服器而言,顯然,嘿嘿嘿~~~
epoll的基礎知識吧大家在網上到處都能找到,不就是epoll_creat 、epoll_ctl、epoll_wait 3函數!大家自己搜去,我也是在學習。。。
此處主要是貼上自己的測試的一些垃圾代碼,與大家共勉!呵呵呵~
哦,忘了要注意一下:
epoll_ctl epoll的事件注冊函數,其events參數可以是以下宏的集合:
EPOLLIN: 表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);
EPOLLOUT: 表示對應的文件描述符可以寫;
EPOLLPRI: 表示對應的文件描述符有緊急的數據可讀(這里應該表示有帶外數據到來);
EPOLLERR: 表示對應的文件描述符發生錯誤;寫已關閉socket pipe broken
EPOLLHUP: 表示對應的文件描述符被掛斷;譬如收到RST包。在注冊事件的時候這個事件是默認添加。
EPOLLRDHUP: 表示對應的文件描述符對端socket關閉事件,主要應用於ET模式下。
在水平觸發模式下,如果對端socket關閉,則會一直觸發epollin事件,驅動去處理client socket。
在邊沿觸發模式下,如果client首先發送協議然後shutdown寫端。則會觸發epollin事件。但是如果處理程序只進行一次recv操作時,根據recv收取到得數據長度來判讀後邊是

否還有需要處理的協議時,將丟失客戶端關閉事件。
EPOLLET: 將EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里

server端:

[cpp] view plain
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h> /* socket類定義需要*/
#include <sys/epoll.h> /* epoll頭文件 */
#include <fcntl.h> /* nonblocking需要 */
#include <sys/resource.h> /* 設置最大的連接數需要setrlimit */

#define MAXEPOLL 10000 /* 對於伺服器來說,這個值可以很大的! */
#define MAXLINE 1024
#define PORT 6000
#define MAXBACK 1000

//!> 設置非阻塞
//!>
int setnonblocking( int fd )
{
if( fcntl( fd, F_SETFL, fcntl( fd, F_GETFD, 0 )|O_NONBLOCK ) == -1 )
{
printf("Set blocking error : %d\n", errno);
return -1;
}
return 0;
}

int main( int argc, char ** argv )
{
int listen_fd;
int conn_fd;
int epoll_fd;
int nread;
int cur_fds; //!> 當前已經存在的數量
int wait_fds; //!> epoll_wait 的返回值
int i;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
struct epoll_event ev;
struct epoll_event evs[MAXEPOLL];
struct rlimit rlt; //!> 設置連接數所需
char buf[MAXLINE];
socklen_t len = sizeof( struct sockaddr_in );

//!> 設置每個進程允許打開的最大文件數
//!> 每個主機是不一樣的哦,一般伺服器應該很大吧!
//!>
rlt.rlim_max = rlt.rlim_cur = MAXEPOLL;
if( setrlimit( RLIMIT_NOFILE, &rlt ) == -1 )
{
printf("Setrlimit Error : %d\n", errno);
exit( EXIT_FAILURE );
}

//!> server 套介面
//!>
bzero( &servaddr, sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( PORT );

//!> 建立套接字
if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf("Socket Error...\n" , errno );
exit( EXIT_FAILURE );
}

//!> 設置非阻塞模式
//!>
if( setnonblocking( listen_fd ) == -1 )
{
printf("Setnonblocking Error : %d\n", errno);
exit( EXIT_FAILURE );
}

//!> 綁定
//!>
if( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( struct sockaddr ) ) == -1 )
{
printf("Bind Error : %d\n", errno);
exit( EXIT_FAILURE );
}

//!> 監聽
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d\n", errno);
exit( EXIT_FAILURE );
}

//!> 創建epoll
//!>
epoll_fd = epoll_create( MAXEPOLL ); //!> create
ev.events = EPOLLIN | EPOLLET; //!> accept Read!
ev.data.fd = listen_fd; //!> 將listen_fd 加入
if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev ) < 0 )
{
printf("Epoll Error : %d\n", errno);
exit( EXIT_FAILURE );
}
cur_fds = 1;

while( 1 )
{
if( ( wait_fds = epoll_wait( epoll_fd, evs, cur_fds, -1 ) ) == -1 )
{
printf( "Epoll Wait Error : %d\n", errno );
exit( EXIT_FAILURE );
}

for( i = 0; i < wait_fds; i++ )
{
if( evs[i].data.fd == listen_fd && cur_fds < MAXEPOLL )
//!> if是監聽埠有事
{
if( ( conn_fd = accept( listen_fd, (struct sockaddr *)&cliaddr, &len ) ) == -1 )
{
printf("Accept Error : %d\n", errno);
exit( EXIT_FAILURE );
}

printf( "Server get from client !\n"/*, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port */);

ev.events = EPOLLIN | EPOLLET; //!> accept Read!
ev.data.fd = conn_fd; //!> 將conn_fd 加入
if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev ) < 0 )
{
printf("Epoll Error : %d\n", errno);
exit( EXIT_FAILURE );
}
++cur_fds;
continue;
}

//!> 下面處理數據
//!>
nread = read( evs[i].data.fd, buf, sizeof( buf ) );
if( nread <= 0 ) //!> 結束後者出錯
{
close( evs[i].data.fd );
epoll_ctl( epoll_fd, EPOLL_CTL_DEL, evs[i].data.fd, &ev ); //!> 刪除計入的fd
--cur_fds; //!> 減少一個唄!
continue;
}

write( evs[i].data.fd, buf, nread ); //!> 回寫

}
}

Ⅱ 如何在linux下實現event事件機制

一、Libevent簡介

libevent是一個基於事件觸發的網路庫,適用於windows、linux、bsd等多種平台,內部使用select、epoll、kqueue等系統調用管理事件機制。
特點:
事件驅動,高性能;
輕量級,專注於網路,不如ACE那麼臃腫龐大,只提供了簡單的網路API的封裝,線程池,內存池,遞歸鎖等均需要自己實現;
開放源碼,代碼相當精煉、易讀;
跨平台,支持Windows、Linux、BSD和Mac OS;
支持多種I/O多路復用技術(epoll、poll、dev/poll、select和kqueue等),在不同的操作系統下,做了多路復用模型的抽象,可以選擇使用不同的模型,通過事件函數提供服務;
支持I/O,定時器和信號等事件;
採用Reactor模式;

二、源碼組織結構

Libevent 的源代碼雖然都在一層文件夾下面,但是其代碼分類還是相當清晰的,主要可分為頭文件、內部使用的頭文件、輔助功能函數、日誌、libevent框架、對系 統I/O多路復用機制的封裝、信號管理、定時事件管理、緩沖區管理、基本數據結構和基於libevent的兩個實用庫等幾個部分,有些部分可能就是一個源文件。
1)頭文件
主要就是event.h:事件宏定義、介面函數聲明,主要結構體event的聲明;
2)內部頭文件
xxx-internal.h:內部數據結構和函數,對外不可見,以達到信息隱藏的目的;
3)libevent框架
event.c:event整體框架的代碼實現;
4)對系統I/O多路復用機制的封裝
epoll.c:對epoll的封裝;
select.c:對select的封裝;
devpoll.c:對dev/poll的封裝;
kqueue.c:對kqueue的封裝;
5)定時事件管理
min-heap.h:其實就是一個以時間作為key的小根堆結構;
6)信號管理
signal.c:對信號事件的處理;
7)輔助功能函數
evutil.h 和evutil.c:一些輔助功能函數,包括創建socket pair和一些時間操作函數:加、減和比較等。
8)日誌
log.h和log.c:log日誌函數
9)緩沖區管理
evbuffer.c和buffer.c:libevent對緩沖區的封裝;
10)基本數據結構
compat/sys下的兩個源文件:queue.h是libevent基本數據結構的實現,包括鏈表,雙向鏈表,隊列等;_libevent_time.h:一些用於時間操作的結構體定義、函數和宏定義;
11)實用網路庫
http和evdns:是基於libevent實現的http伺服器和非同步dns查詢庫;

閱讀全文

與epoll頭文件相關的資料

熱點內容
maya粒子表達式教程 瀏覽:84
抖音小視頻如何掛app 瀏覽:283
cad怎麼設置替補文件 瀏覽:790
win10啟動文件是空的 瀏覽:397
jk網站有哪些 瀏覽:134
學編程和3d哪個更好 瀏覽:932
win10移動硬碟文件無法打開 瀏覽:385
文件名是亂碼還刪不掉 瀏覽:643
蘋果鍵盤怎麼打開任務管理器 瀏覽:437
手機桌面文件名字大全 瀏覽:334
tplink默認無線密碼是多少 瀏覽:33
ipaddgm文件 瀏覽:99
lua語言編程用哪個平台 瀏覽:272
政采雲如何導出pdf投標文件 瀏覽:529
php獲取postjson數據 瀏覽:551
javatimetask 瀏覽:16
編程的話要什麼證件 瀏覽:94
錢脈通微信多開 瀏覽:878
中學生學編程哪個培訓機構好 瀏覽:852
榮耀路由TV設置文件共享錯誤 瀏覽:525

友情鏈接