epollサーバプログラミング-demo
簡単なEchoServerです
構成されたネットワーク・アドレスで傍受(0.0.0.0でも傍受)
epollハンドルの作成
epollキューにソケットを追加
epollキューで待機し、読み書きイベントが発生した場合、ユーザー関数をコールバックします.
単純な起動スレッド
ユーザコールバック関数
makefileを含むプロジェクトソースファイル.
http://hi.csdn.net/attachment/201112/30/0_1325239083n82M.gif
構成されたネットワーク・アドレスで傍受(0.0.0.0でも傍受)
// create listen
int
init_listen_sock(int epsfd, unsigned short port)
{
std::vector<int> ip_list;
if (!get_ipv4_addr(ip_list))
return 1;
for (int i = 0; i < ip_list.size(); i++)
{
int sfd = 0;
if ((sfd = listen_on(ip_list[i], port)) < 0)
return 1;
int ipv4 = ip_list[i];
unsigned char * pipv4 = (unsigned char *)&ipv4;
LOG_INFO("listen on host: [%d.%d.%d.%d : %d]
",
pipv4[0],
pipv4[1],
pipv4[2],
pipv4[3],
port
);
if (ep_add(epsfd, sfd, true))
return 1;
}
return 0;
}
epollハンドルの作成
int ep_init()
{
return epoll_create(5);
}
epollキューにソケットを追加
int ep_add(int epfd, int sfd, bool is_listen_sock)
{
struct epoll_event evt;
evt.events = EPOLLIN
//| EPOLLOUT
| EPOLLET
;
evt.data.ptr = malloc(sizeof(struct epoll_sock_t));
epoll_sock_t * ptr = (epoll_sock_t *) evt.data.ptr;
ptr->sock_fd = sfd;
ptr->listen = is_listen_sock;
int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &evt);
return ret;
}
epollキューからソケットを削除 int ep_del(int epfd, int sfd)
{
int ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sfd, 0);
return ret;
}
epollハンドルを閉じる int ep_shutdown(int epfd)
{
close(epfd);
return 0;
}
epollキューで待機し、読み書きイベントが発生した場合、ユーザー関数をコールバックします.
int
ep_wait(int epfd, ep_wait_cb_t epw_cb, void * userdata)
{
struct epoll_event evts[EP_MAX_WAIT_NR] = { 0 };
for (;;)
{
int nfds = 0; errno = 0;
if (0 >= (nfds = epoll_wait(epfd, evts, EP_MAX_WAIT_NR, -1)) && errno != EINTR)
{
break;// stop
}
for (int i = 0; i < nfds; i++)
{
epw_cb(epfd, &evts[i], userdata);
}
}
}
単純な起動スレッド
void * ep_thread(void * args)
{
int epfd = 0;
if ((epfd = ep_init()) <= 0)
return 0;
unsigned short port = 8000;
if (init_listen_sock(epfd, port))
{
return 0;
}
void * userdata = 0;
if (ep_wait(epfd, ep_event_callback, userdata))
{
return 0;
}
if (ep_shutdown(epfd))
{
return 0;
};
return (void *)0;
}
ユーザコールバック関数
int
ep_event_callback(int epfd, struct epoll_event * evt, void * userdata)
{
epoll_sock_t * ptr = (epoll_sock_t *) (evt->data.ptr);
if (evt->events & EPOLLIN)
{
printsockinfo(ptr->sock_fd);
if (ptr->listen) // for listen socket
{
sockaddr_in csa;
socklen_t csalen = sizeof(csa);
int clientsfd = 0;
errno = 0;
while ((clientsfd = accept(ptr->sock_fd, (struct sockaddr *) &csa, &csalen)) > 0)
{
if (setnonblocking(clientsfd))
{
LOG_ERROR("fail to set client socket to non-blocking.
");
close(clientsfd);
continue;
}
if (ep_add(epfd, clientsfd, false))
{
LOG_ERROR("fail to add client socket to epoll.
");
close(clientsfd);
continue;
}
}
if (errno != EAGAIN && errno != EINTR)
close(ptr->sock_fd);
}
else
{
errno = 0;
char msg [0x200] = "";
while (recv(ptr->sock_fd, msg, 0x200, 0) > 0)
{
tm_printstamp();
LOG_INFO(" - %s \r
", msg);
fflush(stdout);
}
if (errno != EAGAIN && errno != EINTR)
{
close(ptr->sock_fd);
LOG_ERROR("errno=[%d]
", errno);
}
}
}
else if (evt->events & EPOLLERR)
{
LOG_INFO("catch an EPOLLERR, sockfd=[%d]. errno=[%d]
", ptr->sock_fd, errno);
close(ptr->sock_fd);
}
else
{
LOG_INFO("epoll events [%d] Ignored, sockfd = [%d].
", evt->events, ptr->sock_fd);
}
return 0;
}
makefileを含むプロジェクトソースファイル.
http://hi.csdn.net/attachment/201112/30/0_1325239083n82M.gif