[epoll] 简单的 echo server
2008-07-19 15:28:03| 分类:
net
| 标签:
|举报
|字号大中小 订阅
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#define MY_MAX_FD 5
int efd;
// ------------
void release_epoll()
{
close(efd);
}
void init_epoll()
{
efd = epoll_create(MY_MAX_FD);
if ( efd == -1 )
errx(1, "epoll_create() fail");
atexit(release_epoll);
}
void add_epoll_event(int fd, int events)
{
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
if ( epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1 )
errx(1, "epoll_ctl(add) fail");
}
void del_epoll_event(int fd)
{
if ( epoll_ctl(efd, EPOLL_CTL_DEL, fd, NULL) == -1 )
errx(1, "epoll_ctl(del) fail");
}
// ------------
int setnonblock(int fd)
{
int flags;
flags = fcntl(fd, F_GETFL);
if (flags < 0)
goto label_nonblock_error;
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0)
goto label_nonblock_error;
return 0;
label_nonblock_error:
return -1;
}
int bind_and_listen(int fd, int port)
{
struct sockaddr_in in_addr;
int reuseaddr_on = 1;
// addr reuse
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseaddr_on, sizeof(reuseaddr_on));
// bind & listen
bzero(&in_addr, sizeof(in_addr));
in_addr.sin_family = AF_INET;
in_addr.sin_addr.s_addr = htonl(INADDR_ANY);
in_addr.sin_port = htons(port);
if ( bind(fd, (struct sockaddr *) &in_addr, sizeof(in_addr)) == -1 )
errx(1, "bind() fail");
if ( listen(fd, 5) == -1 )
errx(1, "listen() fail");
// set non-block
setnonblock(fd);
return 0;
}
// ------------
void do_use_fd(int fd)
{
int n;
char buf[1024];
printf("fd read: %d\n", fd);
n = read(fd, buf, sizeof(buf));
if ( n == -1 )
return;
else if ( n == 0 )
{
del_epoll_event(fd);
close(fd);
printf("fd close: %d\n", fd);
return;
}
write(fd, buf, n);
}
void do_listen_fd(int listen_fd)
{
int client_fd;
while (1)
{
client_fd = accept(listen_fd, NULL, NULL);
if ( client_fd == -1 )
{
if ( errno == EAGAIN )
{
printf("accept finish\n");
break; // no conn any more
}
else if ( errno == EINTR )
continue;
}
add_epoll_event(client_fd, EPOLLIN);
printf("new client: %d\n", client_fd);
}
}
int main()
{
int listen_fd, n, i;
struct epoll_event ev_list[MY_MAX_FD];
init_epoll();
listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( listen_fd == -1 )
errx(1, "socket() listen_fd");
bind_and_listen(listen_fd, 7777);
// add to epoll
add_epoll_event(listen_fd, EPOLLIN);
printf("bind & listen ...\n");
while (1)
{
n = epoll_wait(efd, ev_list, MY_MAX_FD, -1);
if ( n == -1 )
errx(1, "epoll_wait() fail");
printf("wait return, active fd count: %d\n", n);
for ( i = 0; i < n; i++ )
{
struct epoll_event *ev = &ev_list[i];
if ( ev->data.fd == listen_fd )
{
do_listen_fd(listen_fd);
}
else
{
do_use_fd(ev->data.fd);
}
}
}
return 0;
}
评论这张
转发至微博
转发至微博
评论