一个简单的EchoServer.
在配置的网络地址上监听(也可以监听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]\n",
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.\n");
close(clientsfd);
continue;
}
if (ep_add(epfd, clientsfd, false))
{
LOG_ERROR("fail to add client socket to epoll.\n");
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\n", msg);
fflush(stdout);
}
if (errno != EAGAIN && errno != EINTR)
{
close(ptr->sock_fd);
LOG_ERROR("errno=[%d]\n", errno);
}
}
}
else if (evt->events & EPOLLERR)
{
LOG_INFO("catch an EPOLLERR, sockfd=[%d]. errno=[%d]\n", ptr->sock_fd, errno);
close(ptr->sock_fd);
}
else
{
LOG_INFO("epoll events [%d] Ignored, sockfd = [%d].\n", evt->events, ptr->sock_fd);
}
return 0;
}
项目源文件,包括makefile.
http://hi.csdn.net/attachment/201112/30/0_1325239083n82M.gif