整体思路: 创建socket监听请求,收到请求后线程分离,在线程中进行请求数据的解析;根据解析到的消息我们分类处理,目前该文件服务器可提供的文件包括html、css、jpg、gif;
1.监听请求,; 首先设置了端口复用,这个从字面理解就好了,就是说该端口上可以绑定多个socket;分配套接字,Http文件服务器是基于TCP传输协议; 初始化监听的地址结构体; 套接字与地址结构体绑定;
2.循环监听,这里的accept函数是从步骤1中的listen函数的等待请求队列里接受一个连接; 自定义结构体,打包了文件描述符,地址,地址大小; 创建线程并分离,所有的处理工作在do_work函数中;
3.do_work()函数
3.1 初始化
3.2 进入函数后不要盲目的直接调用开始处理请求行,我们先判断这个客户端的下一步动作,
如果recv返回了但是num为0,说明客户端套接字主动断开连接,这里直接goto到线程
收尾工作;
3.3 处理请求头的第一行数据,一般格式是 (方法 文件路径 协议版本)
例如:GET /index.html HTTP/1.1
注意: #define ISsp(x) isspace((int)(x)) //用于判断空格;
get_line()函数 获取一行数据,自定义函数,以 rn判断;
3.4 获取URL,即获取客户端想要请求的文件路径;
3.5 客户端请求的URL一般是请求的Http文件服务器的站点目录
如果请求的是 /index.html ===> 那么在我的设置里对应的 是/root/Project/WebFileServer/File/index.html
一定要区分客户端请求的根目录其实是服务器上的站点根目录
3.6 返回文件根据cgi的值,cgi等于1代表是POST,我们提交到cgi程序处理; cgi等于0代表是普通的GET,文件服务器直接返回静态文件;
4.get_line()函数 : 该函数为Tinyhttpd源码,可以放心的使用
5.提供静态文件(其中包括html、css、jpg、gif、下载文件)
6.这里给出只给出提供html文件的函数和下载文件函数;其他函数实现类似
下载文件需要注意的是返回类型,在html返回中服务器的发送的响应头里,Content-Type设置的是text/html;在下载类型中需要采用application/octet-stream,此为下载类型,用二进制传输文件;
注意:该下载文件实现是用的大文件分块传输,切记发送数据时要保证文件要关闭,不要在打开文件的状态传输数据,当客户端关闭时服务器会退出;
7.文件上传
首先是客户端,一般采用POST方法提交到文件服务器上的一个cgi程序,在步骤3.6中我们实现了提供静态文件,这里来描述如果利用cgi上传文件到服务器;
步骤为:客户端按下按键发送一个带有文件的POST请求 ==> 服务器接收请求并获取文件信息 ==> 服务器接收文件数据并存储
客户端的提交信息:
POST /CGI/down.cgi?filename=xxx HTTP/1.1rn
… …rnrn
(file data)
这里请求了根目录下CGI目录中的down.cgi这个程序,提交的文件名放在xxx这个位置,这部分是在客户端实现的;服务器收到请求调用down.cgi ; 该cgi可以用C写也可以用Shell,Python… … 本次采用的C语言实现cgi程序;
感谢你耐心的看完了这篇文章,希望能够帮助到你。