#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <errno.h>
#include "common.h"
#include "serversignal.h"
#include "server_epoll.h"
static int open_socket(struct sockaddr_in* paddr);
static int accept_client(int sockfd, struct sockaddr_in* paddr);
static int process_request(int connfd);
static volatile sig_atomic_t graceful=0;
#define HTTP_PORT 18080
#define BACK_LOG 50
#define MAX_FDS 100
#define SOCKLEN sizeof(struct sockaddr_in)
#define err_log_exit()\
do{\
perror("server failed");\
fprintf(stderr, "file %s line %d\n", __FILE__, __LINE__);\
exit(EXIT_FAILURE);\
}while(0)\
#define err_msg_exit(msg)\
do{\
perror(msg);\
fprintf(stderr, "file %s line %d\n", __FILE__, __LINE__);\
exit(EXIT_FAILURE);\
}while(0)\
static int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
{
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
signal_init();
int max_worker = 2;
int child = 0;
int epollfd = 0;
struct sockaddr_in saddr;
int sockfd = 0;
int nfds = 0;
int index = 0;
int fd = 0;
int acceptfd = 0;
struct epoll_event *events;
memset(&saddr, 0, sizeof(struct sockaddr_in));
sockfd=open_socket(&saddr);
if(sockfd == -1)
err_log_exit();
while(!graceful&&!child){
if(max_worker>0){
switch(fork()){
case -1:
err_log_exit();
break;
case 0:
child =1;
break;
default:
printf("child creat\n");
max_worker--;
break;
}
}else{
int status =0;
if( -1 != wait(&status)){
//max_worker++;
fprintf(stderr, "child quit\n");
}
}
}
if(!child){
fprintf(stderr, "before quit, kill all child\n");
kill(0, SIGINT);
sleep(2);
return 0;
}
//child
epollfd = server_epoll_create(MAX_FDS+1);
if(epollfd == -1)
err_log_exit();
if(server_epoll_event_add(epollfd, sockfd) == -1)
err_log_exit();
events = (struct epoll_event*)malloc(MAX_FDS*sizeof(struct epoll_event));
memset(events, 0, MAX_FDS*sizeof(struct epoll_event));
/* close stdin and stdout, as they are not needed */
/* move stdin to /dev/null */
if (-1 != (fd = open("/dev/null", O_RDONLY))) {
close(STDIN_FILENO);
dup2(fd, STDIN_FILENO);
close(fd);
}
/* move stdout to /dev/null */
if (-1 != (fd = open("/dev/null", O_WRONLY))) {
close(STDOUT_FILENO);
dup2(fd, STDOUT_FILENO);
close(fd);
}
while(child&&!graceful){
nfds = epoll_wait(epollfd, events, MAX_FDS, 500);
index = 0;
while(index < nfds){
if(events[index].data.fd == sockfd){
acceptfd = accept_client(sockfd, &saddr);
//waking herd
if(acceptfd == -1){
perror("accept failed\n");
}else{
//accept ok
if(server_epoll_event_add(epollfd, acceptfd) == -1)
err_log_exit();
}
}else if(events[index].data.fd == acceptfd){
// receive data from client
// if client close, need avoid TIME_WAIT status
if(process_request(acceptfd) == 0){
fprintf(stderr, "client close, close connection and quit listen connect fd\n");
if(server_epoll_event_del(epollfd, acceptfd) == -1)
err_log_exit();
close(acceptfd);
}
}else{
}
index++;
};
if(nfds == -1){
if (errno == EINTR)
continue;
else{
err_log_exit();
}
}
};
return 0;
}
void server_graceful_set(int g)
{
if(g>0){
g=1;
}else{
g=0;
}
graceful=g;
}
int server_graceful_get()
{
return graceful;
}
static int open_socket(struct sockaddr_in* paddr)
{
int sockfd = 0;
struct sockaddr_in sockaddress;
bzero(&sockaddress, sizeof(sockaddress));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
err_log_exit();
sockaddress.sin_family = AF_INET;
sockaddress.sin_port = htons(HTTP_PORT);
setnonblocking(sockfd);
inet_pton(AF_INET, "10.174.8.163", &(sockaddress.sin_addr));
if(bind(sockfd, (struct sockaddr*)(&sockaddress), sizeof(sockaddress)) == -1)
err_log_exit();
if(listen(sockfd, BACK_LOG) == -1)
err_log_exit();
*paddr = sockaddress;
return sockfd;
}
static int accept_client(int sockfd, struct sockaddr_in* paddr)
{
socklen_t len = SOCKLEN;
int connfd = 0;
if(paddr != NULL)
{
connfd = accept(sockfd, (struct sockaddr*)(paddr), &len);
}else
{
connfd = -1;
}
return connfd;
}
static int process_request(int connfd)
{
char request[1000];
int len = 0;
bzero(request, sizeof(request));
len = recv(connfd, request, sizeof(request), 0);
if(len >0)
fprintf(stderr, "%s\n", request);
return len;
}
#include <unistd.h>
#include <string.h>
#include "server_epoll.h"
int server_epoll_event_add(int epollfd, int sockfd)
{
struct epoll_event ep;
memset(&ep, 0, sizeof(ep));
ep.events = 0;
ep.events |= EPOLLIN;
ep.events |= EPOLLOUT;
ep.data.fd = sockfd;
return epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ep);
}
int server_epoll_event_del(int epollfd, int sockfd)
{
struct epoll_event ep;
memset(&ep, 0, sizeof(ep));
ep.events = 0;
ep.events |= EPOLLIN;
ep.events |= EPOLLOUT;
ep.data.fd = sockfd;
return epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, &ep);
}
int server_epoll_create(int size)
{
int fd = epoll_create(size);
return fd;
}
int server_epoll_close(int fd)
{
return close(fd);
}