高併發網路程式設計之epoll詳解

2021-08-21 06:22:57 字數 3792 閱讀 1278

核心 / 使用者空間記憶體拷貝問題,select需要複製大量的控制代碼資料結構,產生巨大的開銷;

select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件;

select的觸發方式是水平觸發,應用程式如果沒有完成對乙個已經就緒的檔案描述符進行io操作,那麼之後每次select呼叫還是會將這些檔案描述符通知程序。

struct

eventpoll;

struct

epitem

// // a ****** echo server using epoll in linux

// // 2009-11-05

// 2013-03-22:修改了幾個問題,1是/n格式問題,2是去掉了原**不小心加上的et模式;

// 本來只是簡單的示意程式,決定還是加上 recv/send時的buffer偏移

// by sparkling

// #include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define max_events 500

struct

myevent_s

; // set event

void

eventset

(myevent_s *ev, int fd, void (*call_back)

(int, int, void*), void *arg)

// add/mod an event to epoll

void

eventadd

(int epollfd, int events, myevent_s *ev)

}; int op;

epv.data.ptr = ev;

epv.events = ev->events = events;

if(ev->status ==

1) else

if(epoll_ctl(epollfd, op, ev->fd, &epv) <

0) printf(

"event add failed[fd=%d], evnets[%d]\n", ev->fd, events);

else

printf(

"event add ok[fd=%d], op=%d, evnets[%0x]\n", ev->fd, op, events);

} // delete an event from epoll

void

eventdel

(int epollfd, myevent_s *ev)

}; if(ev->status !=

1) return;

epv.data.ptr = ev;

ev->status =

0;epoll_ctl(epollfd, epoll_ctl_del, ev->fd, &epv);

} int g_epollfd;

myevent_s g_events[max_events+

1];

// g_events[max_events] is used by listen fd

void

recvdata

(int fd, int events, void *arg)

;

void

senddata

(int fd, int events, void *arg)

;

// accept new connections from clients

void

acceptconn

(int fd, int events, void *arg)

printf(

"%s: accept, %d", __func__, errno);

return;

} do

} if(i == max_events)

// set nonblocking

int iret =

0;if((iret = fcntl(nfd, f_setfl, o_nonblock)) <

0)// add a read event for receive data

eventset(&g_events[i], nfd, recvdata, &g_events[i]);

eventadd(g_epollfd, epollin, &g_events[i]);

}while(

0);

printf(

"new conn[%s:%d][time:%d], pos[%d]\n", inet_ntoa(

sin.sin_addr),

ntohs(

sin.sin_port), g_events[i].last_active, i);

} // receive data

void

recvdata

(int fd, int events, void *arg)

else

if(len ==

0) else

} // send data

void

senddata

(int fd, int events, void *arg)

} else

} void

initlistensocket

(int epollfd, short port)

intmain

(int argc, char **argv)

// create epoll

g_epollfd = epoll_create(max_events);

if(g_epollfd <=

0) printf(

"create epoll failed.%d\n", g_epollfd);

// create & bind listen socket, and add to epoll, set non-blocking

initlistensocket(g_epollfd, port);

// event loop

struct

epoll_event

events[max_events];

printf(

"server running:port[%d]\n", port);

int checkpos =

0; while(

1) }

int fds = epoll_wait(g_epollfd, events, max_events,

1000);

if(fds <

0) for(

int i =

0; i < fds; i++)

if((events[i].events&epollout)&&(ev->events&epollout))

// write event

} }

// free resource

return

0;

}

高併發網路程式設計之epoll詳解

核心 使用者空間記憶體拷貝問題,select需要複製大量的控制代碼資料結構,產生巨大的開銷 select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件 select的觸發方式是水平觸發,應用程式如果沒有完成對乙個已經就緒的檔案描述符進行io操作,那麼之後每次s...

網路程式設計之併發網路程式設計

之前使用socket模組實現的網路程式設計都不能併發進行連線和通訊的,即乙個客戶端需要等待伺服器和另乙個客戶端通訊完成後才能和服務端進行連線和通訊。python3中提供有乙個高階內建模組socketserver來幫助我們進行併發的網路程式設計。socketserver模組處理網路請求的功能,可以通過...

高併發伺服器程式設計之epoll 二

這裡使用epoll data聯合體中的ptr指標。include include include include include include include include include include define max size 5 typedef struct client info ...