项目笔记 | 基于自建http协议的共享目录服务器

前言

百度网盘存储功能方便了我们存储资料不仅限于物理设备,但是对于普通用户难以忍受限速的操作。在学习了网络编程之后,决定自己写一个基于http协议的共享目录,方便客户端将文件目录上传到服务端,支持目录列表展示,文件上传,文件下载,断点续传。

1. 框架流程

跟着想法画的,难免有些粗糙:
项目笔记 | 基于自建http协议的共享目录服务器

对流程总结一下:

  • 搭建tcp服务器,用epoll进行事件监控
  • 判断事件是监听事件时,放置线程池任务队列,调用任务处理函数
  • 任务处理函数,分为,http请求解析,随后对组织http响应返回给web端
  • 对http请求的方法和参数,路径进行判断

1.如果时GET方法,且有参数,或者POST请求,执行CGI
2.如果为GET方法,查询路径不为空 即为 列表展示否则就是文件下载

3. 请求解析

  1. 先接受整个头部信息,判断有没有空行,如果有则表示整个头部信息接受完整
  2. 通过找到换行符\r\n,划分首行和头部。
  3. 在头部里找到Content-Length字段,即可知道正文长度,后续方便接受正文。

3.1 首行解析

  1. 首先找到空格出现的地方,前面就是请求方法和http协议版本
  2. 空格后面是url和请求参数,通过找到?划分这两个
  3. 请求参数以& 分割,所以每次找到它,以key-value方式存储

3.2 头部解析

  • 头部的信息以: 分割,所以找到每次找到它,就存储前后的信息,也是以map形式存储。

4. 文件上传

这里用到了CGI,如果不用CGI,而是服务器直接处理表单数据,那么大量并发情况下,服务器很容易挂掉

  1. 在父进程了fork子进程,建立匿名管道实现父子进程通信
  2. 由于父进程只需要写,所以关闭读端,子进程只需要读,所以关闭写端
  3. 此外,由于父子进程互相独立,在进程替换后,子进程会失去父进程的文件描述符
  4. 所以将父进程的管道重定向到标准输出,子进程重定向到标准输入。
  5. 将头部信息以环境参数传到子进程
  6. 程序替换后,执行子进程,子进程拿到找到Content-Length,接受正文
  7. 解析表单数据,其实就是解析boudnary,一共三段,数据存放在中间。
  8. 判断文件是否正确,并向父进程返回响应信息。

5. 文件下载

  1. 在头部信息找Range字段,如果没有就是普通文件下载,如果有就是断点续传
  2. 拿到Byte字段,找到Range的开始值和结束值。
  3. 下载这个范围的数据
  4. 组织头部响应,状态码必须是206,还有Content-Range字段,后面跟着刚才Range的范围;
    还有Etag信息,Content-Type信息设置为“application/octet-stream”

6. 列表展示

通过boost库的文件迭代器, 将查询路径的每一个文件,通过boost的文件修改时间,文件大小获取,随后写进输出流中,写进正文里,组织响应给客户端。

项目地址