设为首页 加入收藏

TOP

Linux 用tcp实现的简单http服务器(一)
2019-07-09 16:10:21 】 浏览:305
Tags:Linux tcp 实现 简单 http 服务器

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
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Linux 用libevent实现的简单http.. 下一篇hdu 1427 速算24点【暴力枚举】

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目