Epoll使用示例

#include "xdjaapi.h"
#include "log.h"
#include "utils.h"

#define SERVER_IP "0.0.0.0"
#define SERVER_PORT 1988
#define LISTEN_BACKLOG 5
#define MAX_FDS 256
#define TIMEOUT 3000

static volatile sig_atomic_t isterm = 0;   // 结束信号
static volatile sig_atomic_t isalarm = 0;  // 时钟信号(1秒1次)

static void sig_handler(int sig, siginfo_t *si, void *context)
{
    static siginfo_t empty_siginfo;
    if(!si) si = &empty_siginfo;
    switch(sig)
    {
        case SIGINT: case SIGTERM:
            isterm = sig;
            break;
		case SIGPIPE:
			break;
        case SIGALRM: 
            isalarm = sig;
            break;
        default:
            break;
    }
}

static void signals_register()
{
    struct sigaction act;
    struct itimerval interval;

    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = sig_handler;

    interval.it_interval.tv_sec = 1;
    interval.it_interval.tv_usec = 0;
    interval.it_value.tv_sec = 1;
    interval.it_value.tv_usec = 0;

    sigaction(SIGINT, &act, NULL);
    sigaction(SIGTERM, &act, NULL);
	sigaction(SIGPIPE, &act, NULL);
    sigaction(SIGALRM, &act, NULL);
    setitimer(ITIMER_REAL, &interval, NULL);
}

int main(int argc, char *argv[])
{
	int ret = 0;
	int server_fd = -1;

	int epfd = -1, nfds = 0, loop = 0;
	struct epoll_event event;
	struct epoll_event *pevents = NULL;

	int client_fd = -1;
	unsigned short client_port = 0;
	char client_ip[32+1] = {0};

	char buf_recv[2048+1] = {0};
	char buf_send[2048+1] = {"i hear you!"};

    log_open(basename(argv[0]), 1);
    
	server_fd = tcp_socket();
	if(server_fd == -1)
	{
		log_error("create server socket fd failed: %s", strerror(errno));
		return -1;
	}

	ret = tcp_bind(server_fd, SERVER_IP, SERVER_PORT);
	if(ret == -1)
	{
		log_error("bind server socket fd failed: %s", strerror(errno));
		goto EndP;
	}

	ret = tcp_listen(server_fd, LISTEN_BACKLOG);
	if(ret == -1)
	{
		log_error("listen server socket fd failed: %s", strerror(errno));
		goto EndP;
	}

	epfd = epoll_create(MAX_FDS);
	if(epfd == -1)
	{
		log_error("\"epoll_create\": %s", strerror(errno));
		goto EndP;
	}

	event.data.fd = server_fd;
	event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
	ret = epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &event);
	if(ret == -1)
	{
		log_error("\"epoll_ctl\": %s", strerror(errno));
		goto EndP;	
	}

	pevents = (struct epoll_event*)malloc(MAX_FDS*sizeof(struct epoll_event));
	if(pevents == NULL)
		goto EndP;
	memset(pevents, 0, MAX_FDS*sizeof(struct epoll_event));

	signals_register();
	while(true)	
	{
        if(likely(isalarm))
		{
			log_info("alarm signal: %d", isalarm);
			isalarm = 0;
		}
		
        if(unlikely(isterm))
        {
            log_info("terminate signal: %d", isterm);
			isterm = 0;
            break;
        }

	    log_info("\"epoll_wait\" ...");
		nfds = epoll_wait(epfd, pevents, MAX_FDS, TIMEOUT);
		for(loop = 0; loop < nfds; loop++)
		{
			if(pevents[loop].data.fd == server_fd)
			{
				client_fd = tcp_accept(server_fd, client_ip, 32+1, &client_port);
				if(client_fd == -1)
				{
					log_error("client connect to server failed: %s", strerror(errno));
					continue;
				}
				log_info("client connect to server succeed %s: %d", client_ip, client_port);

				event.data.fd = client_fd;
				event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
				ret = epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &event);
				if(ret == -1)
				{
					log_error("\"epoll_ctl\": %s", strerror(errno));
					tcp_close(client_fd);
					continue;
				}
			}
			else if(pevents[loop].events & EPOLLIN)
			{
				log_info("readable ...");
				ret = tcp_recv(pevents[loop].data.fd, buf_recv, 2048+1);
				if(ret == 0)
				{
					log_info("server recv \"RST\" from client succeed: %d", pevents[loop].data.fd);
					epoll_ctl(epfd, EPOLL_CTL_DEL, pevents[loop].data.fd, NULL);
					tcp_close(pevents[loop].data.fd);
					continue;
				}
				else if(ret == -1)
				{
					log_error("server recv data from client failed: %s", strerror(errno));
					continue;
				}
				log_info("server recv data from client succeed %d: %s", ret, buf_recv);

				event.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
				event.data.fd = pevents[loop].data.fd;
				ret = epoll_ctl(epfd, EPOLL_CTL_MOD, pevents[loop].data.fd, &event);
				if(ret == -1)
				{
					log_error("\"epoll_epoll_ctl\": %s", strerror(errno));
					tcp_close(pevents[loop].data.fd);
					continue;
				}
			}
			else if(pevents[loop].events & EPOLLOUT)
			{
				log_info("writable ...");
				ret = tcp_send(pevents[loop].data.fd, buf_send, strlen(buf_send));
				if(ret == -1)
				{
					log_error("server send to client data failed: %s", strerror(errno));
					continue;
				}
				log_info("server send to client data succeed %d: %s", ret, buf_send);

				event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
				event.data.fd = pevents[loop].data.fd;
				ret = epoll_ctl(epfd, EPOLL_CTL_MOD, pevents[loop].data.fd, &event);
				if(ret == -1)
				{
					log_error("\"epoll_epoll_ctl\": %s", strerror(errno));
					tcp_close(pevents[loop].data.fd);
					continue;
				}
			}
			else if(pevents[loop].events & EPOLLERR || pevents[loop].events & EPOLLHUP)
			{
				epoll_ctl(epfd, EPOLL_CTL_DEL, pevents[loop].data.fd, NULL);
				tcp_close(pevents[loop].data.fd);
				continue;
			}
		}
	}

EndP:
	if(epfd >= 0) close(epfd);
	if(pevents != NULL) free(pevents);
	if(server_fd >= 0) tcp_close(server_fd);
	log_close();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值