核心 / 使用者空間記憶體拷貝問題,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 ...