#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <pthread.h>
#include <signal.h>
#include "init.h"
#include "request.h"
#include "response.h"
#define BACKLOG 4096
#define DEFAULT_PROT 5000
#define MAX_EVENTS 5000
#define MAX_FDS 5000
static int listenfd;
static int port;
static char ip[16];
static struct sockaddr_in addr_local;
static req_header r_header;
static int init_net(void);
static int do_cmdline(int argv, char **argc);
void handler(int sig)
{
close(listenfd);
exit(0);
}
int main(int argv, char *argc[])
{
int nfds;
int nsockfd;
int sfd;
int epfd;
int sin_size;
int i, j, num;
FILE *fp;
signal(SIGINT, handler);
struct sockaddr_in addr_remote;
struct epoll_event events[MAX_EVENTS];
/* 处理命令行参数 */
if (!do_cmdline(argv, argc))
exit(-1);
if (!init_net())
exit(-1);
epfd = epoll_create(MAX_FDS);
if (epfd < 0)
{
perror("epoll_create()");
exit(-1);
}
set_nblocking(listenfd);
register_read_fd(epfd, listenfd);
sin_size = sizeof(struct sockaddr_in);
num = 0;
while(1)
{
printf("start epoll_wait\n");
nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (i = 0; i < nfds; i++)
{
if (events[i].data.fd == listenfd)
{
nsockfd = accept(listenfd, (struct sockaddr *)&addr_remote, &sin_size);
if (nsockfd < 0)
{
perror("accept()");
continue;
}
set_nblocking(nsockfd);
printf("OK:Server has got connect from %s\n", (char *)inet_ntoa(addr_remote.sin_addr));
if (!register_read_fd(epfd, nsockfd))
{
perror("register_read_fd");
close(nsockfd);
continue;
}
num++;
}
else if (events[i].events & EPOLLIN)
{
if ((sfd = events[i].data.fd) < 0)
{
num--;
continue;
}
if (!(fp = fdopen(sfd, "a+")))
{
perror("fdopen()");
remove_read_fd(epfd, sfd);
close(sfd);
num--;
continue;
}
init_rq_struct(&r_header);
getpeername(sfd, (struct sockaddr *)&addr_remote, &sin_size);
strcpy(r_header.client_addr, (char *)inet_ntoa(addr_remote.sin_addr));
if (do_recvdata(fp, &r_header, sfd) < 0)
{
remove_read_fd(epfd, sfd);
fclose(fp);
close(sfd);
num--;
continue;
}
if (send_to_client(sfd, &r_header) < 0)
{
remove_read_fd(epfd, sfd);
fclose(fp);
close(sfd);
num--;
continue;
}
if (!strcmp(r_header.http_vision, "HTTP/1.0") &&
strcmp(r_header.connection, "Keep-Alive"))
{
printf("Http/1.0\n");
remove_read_fd(epfd, sfd);
fclose(fp);
close(sfd);
num--;
continue;
}
printf(".......\n");
printf("-------\n");
}
}
}
exit(1);
}
static int init_net(void)
{
int n;
/* 获取socket描述符 */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Error");
return 0;
} else {
printf("OK: Obtain Socket Descritor successfully.\n");
}
/* 填充本地socket结构体 */
addr_local.sin_family = AF_INET;//协议簇
addr_local.sin_port = htons(port);//监听端口号
//inet_pton(AF_INET, argc[1], &addr_local.sin_addr);
//addr_local.sin_addr.s_addr = htonl(INADDR_ANY);//自动填充本地IP地址
bzero(&(addr_local.sin_zero), 8);//其余位填充0
n = 1;
/* 如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间 */
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));//setsockopt函数设置socket属性
/* 绑定地址和端口 */
if (bind(listenfd, (struct sockaddr *)&addr_local, sizeof(struct sockaddr)) == -1)
{
perror("Error");
return 0;
} else {
printf("OK: Bind the port %d successfully.\n", port);
}
/* 监听连接请求 */
if (listen(listenfd, BACKLOG) == -1)
{
perror("Error");
return 0;
} else {
printf("OK: Listening the Port %d successfully.\n", port);
}
return 1;
}
static int do_cmdline(int argv, char **argc)
{
char tmp[16];
if (argv == 1)
{
printf("OK: Use Default Address and Port.\n");
port = DEFAULT_PROT;
addr_local.sin_addr.s_addr = htonl(INADDR_ANY);
}
else if (argv == 2)
{
strcpy(tmp, argc[1]);
if (!strchr(tmp, '.'))
{
port = fill_port(tmp);
if (port == 0)
return 0;
}
else {
if (!check_addr(tmp))
return 0;
strcpy(ip, argc[1]);
addr_local.sin_addr.s_addr = inet_addr(ip);
printf("OK: Use Default Port Number.\n");
port = DEFAULT_PROT;
}
}
else if (argv == 3) {
strcpy(tmp, argc[1]);
if (!strchr(tmp, '.'))
{
port = fill_port(tmp);
if (port == 0) return 0;
strcpy(tmp, argc[2]);
if (!check_addr(tmp)) return 0;
strcpy(ip, argc[2]);
addr_local.sin_addr.s_addr = inet_addr(ip);
}
else {
if (!check_addr(tmp)) return 0;
strcpy(ip, argc[1]);
addr_local.sin_addr.s_addr = inet_addr(ip);
strcpy(tmp, argc[2]);
port = fill_port(tmp);
if (port == 0) return 0;
}
}
else if (argv > 3) {
printf("Error: More Args from CmdLine\n");
return 0;
}
return 1;
}