#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;
}
Epoll使用示例
最新推荐文章于 2024-04-09 21:51:36 发布