0x13-套接字编程-HTTP服务器(1)
这里不是百科全书,所以只会用最简单,最明了的语言,来讲最实用的TCP编程。
Echo
程序太多,就不再重复了,贯穿整个章节的将会是一个 HTTP 服务器这回是在
Linux
下开发,而不是Windows
TCP
- 囫囵吞枣般的喂完UDP的基本应用,以及一些API的使用,不再赘述TCP的使用,其实是很多我也不懂,(逃。
- 但是,对于API我一向抱以用多少学多少知多少的态度,人生如戏,重在看戏啊。
- 如果想要查找具体的完整的API可以先去查,UNIX网络编程:卷1 + Linux Man手册,其中前者有一些部分实际上已经过时(内核版本跟不上)。更不用说后续加入Linux的一些接口,例如
epoll
。但是其他的接口还是可以参考的,并且十分的详细。 - TCP,这是一个极其复杂的协议,说复杂是因为在这几十年的发展中,对其的优化已经多到令人发指,于此而言,虽说即便不知道这些优化也是可以编写程序,但是建议还是能够熟悉一下流程(两端交互的过程)
- 三次握手,四次挥手,拥塞控制,滑动窗口机制。
- 对于前两个而言,我个人有不同见解,于为什么是三次握手,而不是其他次数,但是由于并不一定被接受,所以我不在这里写入,有兴趣的可以Emali我一起讨论,在面试的时候,我也是会和面试官讨论这个问题,但一直没有满意的答案。
HTTP
- 说了贯穿本章节的是一个 HTTP服务器,如此就一定要说说 HTTP协议 了,如果说前面的TCP即使你不懂它的原理也能编写一个能运行且效率不错的TCP程序的话,那么想写一个HTTP服务器,你要是不懂 HTTP协议,简直是寸步难行。
- 最权威的莫过于 《HTTP权威指南》,你可别想着去看HTTP的标准草案了,那真是神鬼难懂。当然这本书亦是一部大块头,可以选择在网上找一些HTTP协议的资料来补充一些基本知识,再用这本大块头来检索自己需要了解的地方。
- 简单说一下 HTTP 协议
- 实际上这个协议就是 TCP协议在 应用层 的一种封装,换句话说 HTTP服务器实质上还是一个 TCP 程序,只不过 TCP协议 已经被操作系统实现好,留出借口来给你调用,而 HTTP协议 则是完全需要你自己编写。
- 所谓协议就是双方都需要遵守的一个规则,所以 HTTP协议 实质上是一种非实际的东西,最主要的还是包括了一个 状态机,称为 HTTP状态机 ,它的作用就是 解析/生成 HTTP报文,不必太过注意这些名词,最开始想写这个程序的时候,也没有太多顾虑这种名词性的东西。
- 所有的名词都是为了更好的抽象一件事物,就好比数学上的各种 符号,其实本没必要存在,但为了抽象简单的表达,符号就应运而生。所以当你理解不了一个符号的时候,就跳过他,因为你总能找到一个它的替代物(例如符号对应的 公式/展开式,符号对应的定理,定理对应的实际例子),而且比他更加的详细且好理解,这是我三年学习数学总结出来的经验。
- 扯了一些没用的,回归正题
协议版本号
- 主流的就是 HTTP/1.0, HTTP/1.1,其他的在编写本程序时不必太在意
- 需要了解的是这两个版本好的一些功能区别,例如最广为人知的
Connection:
的默认属性
方法
GET
POST
HEAD
- 实际上,在一般的服务器实现中,也只需要实现这三个方法就够了,特别是前两者比较重要,将以
GET
进行程序的方法编写,有兴趣的可以自己实现POST
方法,我的源代码中也已经完成一半了,但并不打算继续完成。
有图有真相
GET / HTTP/1.1\r\n <--- 这是状态行,包括一个请求方法,资源,协议版本
Host: www.wushxin.top\r\n <-- 这是属性头,
Connection: keep-alive\r\n <-- ...
\r\n <-- 一直到空行结束
- 这是最简单的HTTP请求报文,整个报文的意思是请求 资源根目录(注意,是资源根目录) 下的资源(默认 请求根目录且不写什么资源就返回
index.html
),并希望与服务器保持连接。
这里的保持连接和 TCP 协议中的保持连接不一样,具体可以去查找资料,简单来说这是一种不可靠的保持连接,双方都可以在做出保证之后,突然断开连接。可以把它当成不靠谱连接,但是表面工作还是要做的。
有图有真相
200 OK\r\n <-- 状态行,包括一个状态码,状态详情
Host: www.wushxin.top\r\n <-- 属性,
Connection: close\r\n <-- ...
Content-Length: 78\r\n <-- 这个属性,代表空行后面数据有多少
\r\n <-- 直到空行
<html><body><p>Hello, That is the Resource which you Request!</body></html>
这是很简单的一种返回报文,
Content-Length
属性在这里特别重要!绝对不能缺少,它给对端一种信息就是,这个报文的结束位置在哪里。在上述报文中,每行的末尾都有
\r\n
这是HTTP协议 用来表达行末的一个标志,而且,HTTP协议 的头部和文本部有一个空行\r\n
来进行分割。以上就是所有我想要介绍的 HTTP协议的内容,有些零散,还是建议去查找一些资料后再来往下看。
详细计划
- 上面的内容看起来有些零碎,但是做一个程序,还是需要理一理自己的思路。
- 首先,我们的目的是做出一个 并发HTTP服务器, 会涉及到的知识点:
- HTTP协议的实现
- TCP的Socket编程(即套接字编程),所谓网络编程
- 多线程
epoll
机制,暂时不要管select
和poll
这两个相似功能的机制- FastCGI的实现(作为扩展,有兴趣的在最后可以去尝试,资源:FastCGI规范)