I compare_arith(V l, V r) { #define D_L(type, op) case type##_t: c=op(get##type(l), get##type(r)); break #define CMP_(l,r) (((l)>(r))-((l)<(r))) I c; switch (max(T(l),T(r))) { D_L(Z,CMP_); D_L(R,CMP_); } del(l); del(r); return c; #undef CMP_ #undef D_L }
static void signal_handler(int sig) { switch (sig) { case SIGTERM: closing = 1; break; case SIGINT: closing = 1; break; case SIGQUIT: closing = 1; break; case SIGURG: //out of band data handler printf("IGURG received\n"); break; default: D_L("ERROR: never come here!"); break; } }
int main(int argc, char *argv[]) { int echo_port = PORT; if(argc > 1) { LOG("IN %d OUT %d RDHUP %d HUP %d ERR %d", EPOLLIN, EPOLLOUT, EPOLLRDHUP, EPOLLHUP, EPOLLERR); char *endptr = NULL; echo_port = strtol(argv[1], &endptr, 10); if (echo_port <= 0 || echo_port >= LONG_MAX) { LOG("LONG_MIN %ld LONG_MAX %ld, echo port %d", LONG_MIN, LONG_MAX, echo_port); exit(-1); } } LOG("listen to localhost:%d\n", echo_port); // 处理信号 register_sig(SIGTERM, signal_handler); register_sig(SIGINT, signal_handler); register_sig(SIGQUIT, signal_handler); register_sig(SIGPIPE, SIG_IGN); /* 设置SIGURG 的处理函数 sig_urg */ //if(fcntl(ss_fd, F_SETOWN, getpid()) < 0) { //perror("can not set OOB own"); //} //register_sig(SIGURG, signal_handler); int ss_fd = -1; struct sockaddr_in server_addr = {0}; struct sockaddr_in client_addr = {0}; socklen_t addr_in_len = sizeof(struct sockaddr_in); int yes = 1; ss_fd = socket( AF_INET, SOCK_STREAM, 0); if(ss_fd == -1){ perror("create server socket error"); return EXIT_FAILURE; } if (setsockopt(ss_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); return EXIT_FAILURE; } memset(&server_addr, 0, sizeof(struct sockaddr_in)); memset(&client_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(echo_port); server_addr.sin_addr.s_addr = htons(INADDR_ANY); if (bind(ss_fd, (struct sockaddr *)&server_addr, addr_in_len) == -1) { perror("bind server socket error"); return EXIT_FAILURE; } else { printf("bind successfully \n"); } if (listen(ss_fd, BACKLOG) == -1) { perror("listen server socket error"); return EXIT_FAILURE; } else { printf("listen successfully \n"); } printf("listen port %d\n", echo_port); struct epoll_event ev = {0}; struct epoll_event events[MAXEVENTS] = {{0}}; int epfd = epoll_create(MAXCLIENTS); //add server socket to epoll ev.events = EPOLLIN ; //| EPOLLET; ev.data.fd = ss_fd; if(setnonblocking(ss_fd) != 0) { perror("css_fd an not nonblocking"); return EXIT_FAILURE; } epoll_ctl(epfd, EPOLL_CTL_ADD, ss_fd, &ev); if(epfd == -1){ perror("epoll listen socket"); return EXIT_FAILURE; } #define E_TIMEOUT 10 /*********************************** main loop **************************************/ while(!closing) { int ready_fds = epoll_wait(epfd, events, MAXEVENTS, E_TIMEOUT); if(ready_fds == -1){ perror("epoll_wait"); break; } for(int n = 0; n < ready_fds; ++n) { if (events[n].events & EPOLLERR || events[n].events & EPOLLRDHUP || events[n].events & EPOLLHUP) { D_L("ERROR or HUP\n"); if (events[n].data.fd != ss_fd) { closeclient(epfd, events[n].data.fd); } continue; } if (events[n].events & EPOLLIN) { if(events[n].data.fd == ss_fd) { //listening socket while(true) { int c_fd = accept(ss_fd, (struct sockaddr *) &client_addr, &addr_in_len); if(c_fd < 0){ if(errno == EAGAIN){ break; } else if(errno == EINTR){ continue; } else { D_L("accept error %s", strerror(errno)); close(ss_fd); break; } } setnonblocking(c_fd); setkeepalive(c_fd); ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLRDHUP; ev.data.fd = c_fd; //add to epoll events queue if (STAT.conn_amount < MAXCLIENTS) { D_L("total [%d] client, new fd %d Addr: %s:%d", STAT.conn_amount, c_fd,\ inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); if (epoll_ctl(epfd, EPOLL_CTL_ADD, c_fd, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d", c_fd); break; } conn_add(c_fd); } else { const char *refuse_str = "max connections, refuse and close, bye"; D_L("%s\n", refuse_str); send(c_fd, refuse_str, strlen(refuse_str), 0); close(c_fd); } } } else { //common client int fd = events[n].data.fd; conn_list_iter it = conn_list.find(fd); if (it != conn_list.end()) { int left_sz = MAX_BUFSZ - it->second.rsize; int rsz = recv(fd, it->second.rbuf + it->second.rsize, left_sz, 0); if (rsz <= 0) { D_L("get from fd %d err: %s, close it", fd, strerror(errno)); closeclient(epfd, fd); continue; } else if (rsz < left_sz) { //D_L("get from fd %d len: %d", fd, rsz); it->second.rsize += rsz; } else { D_L("recv buf size is to small for bufsz %d fd %d len %d", MAX_BUFSZ, fd, rsz); closeclient(epfd, fd); continue; } } else { D_L("get unknown fd %d EPOLLIN", fd); } } } if (events[n].events & EPOLLOUT) { int fd = events[n].data.fd; conn_list_iter it = conn_list.find(fd); if (it != conn_list.end()) { if (it->second.wsize == 0 && it->second.rsize == 0) { continue; } int nop_sz = it->second.rsize; int left_sz = MAX_BUFSZ - it->second.wsize; if (nop_sz > left_sz) { //buffer too small, send first int wsz = send(fd, it->second.wbuf, it->second.wsize, 0); if (wsz < 0) { D_L("send to fd %d err: %s", fd, strerror(errno)); if (errno == EINTR || errno == EAGAIN) { continue; } closeclient(epfd, fd); continue; } if (wsz != it->second.wsize) { memmove(it->second.wbuf, it->second.wbuf + wsz, it->second.wsize - wsz); } it->second.wsize -= wsz; } left_sz = MAX_BUFSZ - it->second.wsize; if (nop_sz > left_sz) { D_L("send buf size to small for fd %d nop_size %d left_size %d", fd, nop_sz, left_sz); closeclient(epfd, fd); continue; } memcpy(it->second.wbuf + it->second.wsize, it->second.rbuf, nop_sz); it->second.wsize += nop_sz; it->second.rsize -= nop_sz; char *buf = it->second.wbuf; int wsz = send(fd, buf, it->second.wsize, 0); if (wsz < 0) { if (errno == EINTR || errno == EAGAIN) { continue; } D_L("send to fd %d err: %s, close it", fd, strerror(errno)); closeclient(epfd, fd); continue; } it->second.wsize -= wsz; } else { D_L("get unknown fd %d EPOLLOUT", fd); closeclient(epfd, fd); } } //D_L("unkown events get fd %d:%x", events[n].data.fd, events[n].events); } } close(epfd); return 0; }