Linux 用tcp实现的简单http服务器
main.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include "epoll.h"
int main(int argc, char** argv){
if(argc != 3){
printf("eg. port resource_path\n");
exit(1);
}
int port = atoi(argv[1]);
int ret = chdir(argv[2]);
if(ret == -1){
perror("chdir error");
exit(1);
}
int lfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
if(ret == -1){
perror("bind err");
exit(1);
}
listen(lfd, 64);
epoll_run(lfd);
}
epoll.h
#define EVENT_MAX 1024
void epoll_run(int lfd);
void do_accept(int lfd, int efd);
void do_read(int cfd, int efd);
int get_line(int sock, char *buf, int size);
void http_get_request(const char* line, int cfd);
void send_respond_head(int cfd, int no, const char* desp, const char* type, long len);
const char *get_file_type(const char *name);
void send_file(int cfd, const char* path);
void disconnect(int cfd, int epfd);
void send_dir(int cfd, const char* path);
void encode_str(char* to, int tosize, const char* from);
void decode_str(char *to, char *from);
epoll.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include "epoll.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
void epoll_run(int lfd){
int efd = epoll_create(EVENT_MAX);
if(efd == -1){
perror("epoll_create err");
exit(1);
}
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = lfd;
int ret = epoll_ctl(efd, EPOLL_CTL_ADD, lfd, &ev);
if(ret == -1){
perror("epoll_ctl err");
exit(1);
}
struct epoll_event evs[EVENT_MAX];
while(1){
ret = epoll_wait(efd, evs, EVENT_MAX, -1);
if(ret == -1){
perror("epoll_wait err");
exit(1);
}
for(int i = 0; i < ret; ++i){
if(evs[i].data.fd == lfd){
do_accept(lfd, efd);
}
else {
do_read(evs[i].data.fd, efd);
}
}
}
}
void do_read(int cfd, int efd){
char line[1024];
int len = get_line(cfd, line, sizeof(line));
printf("head:%s", line);
while(len){
char buf[1024];
len = get_line(cfd, buf, sizeof buf);
printf("%s", buf);
}
if(strncasecmp("get", line, 3) == 0){
http_get_request(line, cfd);
disconnect(cfd, efd);
}
}
void http_get_request(const char* line, int cfd){
char method[12] = {0};
char res[1024] = {0};
sscanf(line, "%[^ ] %[^ ]", method, res);
// 转码 将不能识别的中文乱码 - > 中文
// 解码 %23 %34 %5f
char destr[1024];
decode_str(destr, res);
// 处理path /xx
// 去掉path中的/
char* file = destr + 1;
char fbuf[1024];
if(strcmp(res, "/") == 0){
file = "./";
//getcwd(fbuf, sizeof(fbuf));
//printf("root:[%s]\n", fbuf);
// file = fbuf;
}
struct stat st;
printf("file:[%s]\n", file);
int ret = stat(file, &st);
if(ret == -1){
//todo 404
perror("stat error");
exit(1);
}
if(S_ISDIR(st.st_mode)){
//di