2023年11月28日发(作者:)

从零开始:编写⼀个Web服务器---HTTP部分详细讲解以及代码实现(⼀)

HTTP部分详细讲解以及代码实现

HTTP—Hyper Text Transfer Protocol(超⽂本传输协议)

HTTP(HyperText Transfer Protocol,超⽂本传输协议)是⼀种⽤于分布式、协作式和超媒体信息系统的应⽤层协议。HTTP 是万维⽹

的数据通信的基础。

HTTP请求过程

这⾥给出⼀篇参考博客:

HTTP请求分类

请求⽅法意义

OPTIONS请求⼀些选项信息,允许客户端查看服务器的性能

GET请求指定的页⾯信息,并返回实体主体

HEAD类似于 get 请求,只不过返回的响应中没有具体的内容,⽤于获取报头

向指定资源提交数据进⾏处理请求(例如提交表单或者上传⽂件)。数据被包含在请求体中。POST请求可能会导致新的资源的建⽴和/或已有

资源的修改

从客户端向服务器传送的数据取代指定的⽂档的内容PUT

请求服务器删除指定的页⾯DELETE

回显服务器收到的请求,主要⽤于测试或诊断TRACE

POST

下⾯给出这些请求,在代码层⾯的表现,如果你想查看⾃⼰当前浏览器所发出的HTTP报⽂,按F12,找到Network,然后F5刷新界⾯,随

便点击Name中的⼀项,找到Request Headers即可显⽰出当前的请求头情况。

GET / HTTP/1.1

Host: 192.168.0.23:47310

Connection: keep-alive

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*; q = 0.8

Accept - Encoding: gzip, deflate, sdch

1xx:表⽰通知信息,如请求收到了或正在进⾏处理

100 Continue:继续,客户端应继续其请求

101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更⾼级的协议,例如,切换到 HTTP 的新

版本协议

2xx:表⽰成功,如接收或知道了

200 OK: 请求成功

POST / HTTP / 1.1

Host: 192.168.0.23 : 47310

Connection : keep - alive

Content - Length : 10

Cache - Control : max - age = 0

Origin : http ://192.168.0.23:40786

Upgrade - Insecure - Requests : 1

User - Agent : Mozilla / 5.0 (Windows NT 6.1; WOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 55.0.2883.87

Safari / 537.36

Content - Type : application / x - www - form - urlencoded

Accept : text / html, application / xhtml + xml, application / xml; q = 0.9, image / webp, */*;q=0.8

Referer: 192.168.0.23:47310/

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.8

Cookie: __guid=179317988.1576500.151.8862; monitor_count=281

Form Data

color=gray

第⼀部分:请求头⾏,包含请求类型、URIHTTP协议版本;

请求信息类型通常有:getpostput等等;

第⼆部分:即紧跟第⼀⾏之后的,请求头部,包含服务器所使⽤的说明信息;

接下来解释⼀下这些说明信息的意思:

1host:请求web服务器的域名地址

2Connection: 表⽰是否持久连接;即keep-alive表⽰持久连接;

3Cache-Control:指定请求和响应的缓存机制;no-cache(不能缓存)、no-store(在请求消息中发送将使得请求和响应消息都不使⽤缓存)、 max-ag

e(客户机可以接收⽣存期不⼤于指定时间(以秒为单位)的响应)、max-stale(客户机可以接收超出超时期间的响应消息)、min-fresh(客户机可以接收响

应时间⼩于当前时间加上指定时间的响应)、 only-if-cached等等

4User-Agent: HTTP协议运⾏的浏览器类型的详细信息;⽐如:⾕歌/67.0.3396.995Accept: 指浏览器可以接收的内容类型;

6Accept-Encoding 客户端浏览器可以⽀持的web服务器返回内容压缩编码类型;

7Accept-Language:浏览器⽀持的语⾔类型,

8Cookie: 某些⽹站为了辨别⽤户⾝份、进⾏ session 跟踪⽽储存在⽤户本地终端上的数据(通常经过加密);例如当我们上⽹时,某些⽹站能准确的推送我

们想要的信息。

第三部分:"rn" --> 分割headerbody部分的分界线

分析功能

ClientServer共有功能

通过刚才的简单讲解,明显看出,在这⼀步骤中我们要完成的只有⼀个任务,就是解析字符串。

因为我们拿到的是“字符串”,好了这样的任务就转化为了,如何⽤C++进⾏字符串解析。相信⼤家在学习C++的过程中,做过不少这⽅⾯

的题。那么做好⼀个针对于HTTP报⽂的字符串的解析,就要先看⼀下,字符串是什么样的形式,我们需要做到哪⼏步。

是否需要分类? 答:需要,不然刚才那么多请求不⽩讲了

是否需要分段解析? 答:需要,Http报⽂按照⾏区分出信息

是否需要判断特殊字符? 答:需要,(显⽽易见是吧)

是否需要区分⼤⼩写 答:需要

Client专属功能

Server专属功能

读者可能会问,我看的别⼈写的HTTP教程都是要什么线程池,然后socket什么。。。。

其实我想写这个教程的⽬的就是按照我⾃⼰的接受思路,由点串成线,由线串成⾯。 如果⼀次性的写出完整实现,就失去了分步⾛的

⽬的。

当然我的最终⽬的是通过这些博客,可以⼀步步的把所学的知识落到代码然后串起来,⽽不是⼀下⼦全摆出来。

代码实现

在进⾏编程时⼀定要注意好,定义与实现的分⽂件形式。良好的代码习惯就是在.h中构建出全部的功能框架,然后在cpp中完成实现。

HTTP

class http_conn

{

public:

//

报⽂的请求⽅法

enum METHOD

{

GET = 0,

POST,

HEAD,

PUT,

DELETE,

TRACE,

OPTIONS,

CONNECT,

PATH

};

//

报⽂解析的结果

enum HTTP_CODE

{

NO_REQUEST = 0,

GET_REQUEST,

BAD_REQUEST,

NO_RESOURCE,

FORBIDDEN_REQUEST,

FILE_REQUEST,

INTERNAL_ERROR,

CLOSED_CONNECTION

};

public:

//

构造和析构

//

如果需要,后期在这⾥回填

http_conn() {}

~http_conn() {}

public:

//

报⽂解析函数

//

返回的是解析出来的情况,根据不同的值完成不同的操作

void process();

//

完成回应的函数

void response();

//

可以看出我们给出的处理函数和回应函数都是没有参数的

//

意味着我们需要在对象内部定义出:读缓冲区,写缓冲区,

NO_REQUEST

请求不完整,需要继续读取请求报⽂数据

GET_REQUEST