您现在的位置是:首页 >技术交流 >【Hello Network】HTTP协议网站首页技术交流
【Hello Network】HTTP协议
HTTP协议
HTTP协议
HTTP协议概念
HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议 是一个简单的请求-响应协议 HTTP通常运行在TCP之上
在编写网络通信代码时 我们可以自己进行协议的定制 但实际有很多优秀的工程师早就已经写出了许多非常成熟的应用层协议 其中最典型的就是HTTP协议
URL概念
首先我们要明白一个概念 我们每天上网的时候请求的图片 文章 css html等我们把它们称之为“资源”
同时我们服务器的后台是使用Linux做的
我们平时写程序的时候使用ip+port确定唯一一个进程 但是我们却无法确定唯一的一个资源
实际上我们所谓的资源都是被保存在网络中的Linux主机上的 而LInux中的所有东西我们都可以看作是一个文件 而文件一般是被保存在磁盘上的
所以说我们可以通过唯一的一个公网IP和路径来确定一份资源
而在我们的生活中IP一般是由域名来呈现的 路径则是由分隔符+目录名呈现
那么什么叫做URL呢?
URL(Uniform Resource Lacator)叫做统一资源定位符也就是我们通常所说的网址
其中服务器地址就是域名对应着我们的IP地址 带层次的文件路径实际上就是我们Linux中的路径
接下来我们来较为全面的认识下上面URL
一、协议方案名
http://
表示的是协议名称 表示请求时需要使用的协议 通常使用的是HTTP协议或安全协议HTTPS
HTTPS是以安全为目标的HTTP通道 在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性
二、登录信息
usr:pass
表示的是登录认证信息 包括登录用户的用户名和密码
虽然登录认证信息可以在URL中体现出来 但绝大多数URL的这个字段都是被省略的 因为登录信息可以通过其他方案交付给服务器
三、服务器地址
www.example.jp表示的是服务器地址 也叫做域名
什么是域名?
域名是IP地址的助记符 便于用户记忆和访问 世界上任何网站都不存在重复域名
简单来理解 他就是为了方便我们记忆而设计出来和IP地址一一对应的助记符
我们之前访问的www.baidu.com
www.qq.com
其实都是域名
我们可以在Linux上尝试ping一下这些域名
ping过之后我们会得到一个ip地址 这个实际上就是百度服务器的ip 如果我们在网页上直接输入这个ip也能够访问百度的网站
四、服务器端口号
80表示的是服务器端口号 HTTP协议和套接字编程一样都是位于应用层的 在进行套接字编程时我们需要给服务器绑定对应的IP和端口 而这里的应用层协议也同样需要有明确的端口号
常见协议对应的端口号:
协议名称 | 对应端口号 |
---|---|
HTTP | 80 |
HTTPS | 443 |
SSH | 22 |
当我们使用某种协议时 该协议实际就是在为我们提供服务 现在这些常用的服务与端口号之间的对应关系都是明确的 所以我们在使用某种协议时实际是不需要指明该协议对应的端口号的 因此在URL当中服务器的端口号一般也是被省略的
五、带层次的文件路径
/dir/index.htm
表示的是要访问的资源所在的路径 这个路径实际上就是我们Linux服务器的一个路径
过前面的域名和端口已经能够找到对应的服务器进程了 此时要做的就是指明该资源所在的路径
我们可以发现Windows上的路径分隔符是 这也就侧面证明了该路径是Linux操作系统上的路径
当我们发起网页请求的时候本质是是得到了一张网页信息 之后浏览器对于这些网页信息进行解释便得到了我们现在所看到的网页
以百度为例 如果我们单击f12之后找到index表 我们会发现这样子的一张html表
我们将这种资源称为网页资源 而HTTP协议之所以称为超文本传输协议正是因为它传输的资源啊可能不是文本资源
六、查询字符串
uid=1
表示的是请求时提供的额外的参数 这些参数是以键值对的形式 通过&符号分隔开的
当我们在百度上搜索HTTP的时候可以在最上面的URL发现这样一段文字
这代表着我们搜索的关键字是HTTP协议
七、片段标识符
ch1
是一个片段标识符
片段标识符是指URL中的一个特殊字符“#”后面的部分 它通常用于指定文档中的某个位置
例如HTML文档中的锚点 在浏览器中 当用户点击一个链接时 浏览器会自动滚动到该链接指定的位置
片段标识符不会被发送到服务器 因此不会影响服务器的响应
urlencode和urldecode
我们再次观察上面的URL
我们可以发现像是 .
?
/
这些字符在外面的URL中有特殊的作用 所以说如果我们要使用这些字符的话 URL就会对这些特殊字符进行转义
其中将这些特殊字符进行转义的过程就叫做encode
将转义后的字符变为可阅读字符的过程就叫做decode
需要注意的是如果我们输入的字符中含有中文 那么中文也会被转义
HTTP协议格式
在TCP/IP四层协议中 应用层最常见的协议是HTTP/HTTPS协议
传输层最常见的协议是TCP/UDP协议
网络层最常见的协议是IP协议
数据链路层最常见的协议是MAC帧
在应用层进行通信的时候 如果不考虑下三层 那么应用层就可以认为是自己和对面的应用层直接通信的
在这四层协议当中 下三层负责的是通信细节 而应用层则负责的是如何使用传输的内容
而这其中最常见的协议是HTTP协议
HTTP服务是基于请求和相应的服务 作为客户端会向服务端发送一个request 客户端接受并分析这个request之后 得出你想要获得什么资源 然后客户端会构建出一个response 完成一次HTTP服务
这种基于request & response的工作方式我们交称为cs格式 其中c是client s是sever
由于HTTP是基于请求和响应的应用层访问 所以说我们必须要了解HTTP的请求和响应格式
HTTP请求协议格式
HTTP的请求协议格式如下:
HTTP协议由以下四部分组成:
我们可以看到HTTP请求由四部分组成
- 请求行:[请求方法]+[url]+[http版本]
- 请求报头:请求的属性 这些属性都是以key: value的形式按行陈列的
- 空行:遇到空行表示请求报头结束
- 请求正文:请求正文允许为空字符串 如果请求正文存在 则在请求报头中会有一个Content-Length属性来标识请求正文的长度
其中前面三部分是由HTTP协议自带的 而请求正文则是用户的相关信息和数据 如果说用户没有信息要上传给服务器 此时正文则为空
如何将HTTP请求的报头与有效载荷进行分离?
首先我们要明白哪里是报头哪里是有效载荷
请求报头:请求行+请求报头
有效载荷:请求正文
细心的同学就可以发现了 事实上报头和有效载荷之间隔着一个空行
如果我们将整个http协议想象成一个线性的结构 每一行都是使用
来进行分隔的 那么如果我们连续读取到两个
的话就说明报头读取完毕了开始读取有效载荷
获取浏览器的HTTP请求
在网络协议栈中 应用层的下一层叫做传输层 而HTTP协议底层通常使用的传输层协议是TCP协议
因此我们可以用套接字编写一个TCP服务器 然后启动浏览器访问我们的这个服务器
由于我们的服务器是直接用TCP套接字读取浏览器发来的HTTP请求 此时在服务端没有应用层对这个HTTP请求进行过任何解析
因此我们可以直接将浏览器发来的HTTP请求进行打印输出 此时就能看到HTTP请求的基本构成
下面我们要写一个简单的TCP服务器 它的作用就是使用TCP套接字来接受浏览器发送过来的数据
代码表示如下
int main()
{
int listen_sock = socket(AF_INET , SOCK_STREAM , 0);
if (listen_sock < 0)
{
cerr << "socket error" << endl;
exit(1);
}
struct sockaddr_in local;
memset(&local , '