最近在看一点网络方面的书籍,对HTTP的请求挺好奇,正好下载了wireshark,那就抓包来好好看看到底是怎样实现的。
我在这次分析中关注的问题点:
(1) 发起一次HTTP请求,为什么要建立TCP的连接?
(2) TCP的连接,典型的三次握手四次挥手到底是什么?
先来说说第一个问题。HTTP是应用层协议,主要依赖于运输层TCP协议。传输层提供了为应用进程之间提供端到端的逻辑通讯。HTTP使用TCP作为他的支撑运输协议。HTTP客户机发起一个与服务器的TCP连接,一旦建立连接,客户机和服务端就可以通过套接字接口访问TCP。

在图片中很明显得能够看到TCP连接中的三次握手、四次挥手的过程。做个图,简单说明下TCP请求的流程:

先来看看TCP的三次握手。从客户端发送连接请求开始

在上图中,可以很明显看到MAC层、网络层、传输层的信息。标志文SYN=1,这是一个请求连接报文,在发送该报文之后,客户端进入SYN_SENDING状态,等待服务器的确认。

服务端收到SYN报文后对报文段进行确认,发送SYN+ACK报文段,此时服务器进入SYN_RECV状态。

客户端收到SYN+ACK的报文段,向服务器段发送ACK报文段,报文段发送完毕之后,客户端和服务器端都进入ESTABLISHED状态。完成TCP的三次握手。
2. 建立TCP连接之后,发起了HTTP的请求,先来观察下HTTP的请求信息

可以看到HTTP的请求报文在TCP请求的基础上增加了HTTP请求的信息,包括协议信息、请求内容信息。这也印证了刘超老师那句话:“只要是在网络上跑的包,都是完整的。可以有下层没上层但是不可能有上层没下层”。

这样的请求格式是不是和教科书中的请求格式能够对应起来。再来具体分析下请求报文中的内容
二层的头信息中是请求来源和目标的MAC地址;IP头中的信息是源IP地址与目标IP地址,以及一些请求的细节信息,这部分暂不考虑;TCP的头中包含的信息由源端口号、目标端口号、SEQ、ACK、请求长度信息;HTTP头信息中就是在浏览器控制台中看到的请求头信息,请求的方式、地址、客户端信息等。HTTP正文就是传输的内容。
在wireshark的抓包分析中,可以看到在发送HTTP请求之后有一长串的TCP请求,由服务端发送到客户端。这部分根据网上查到的资料,这里的分段是上层协议HTTP的应答由多个分段组成,每个分段都是TCP协议的。TCP本身没有分段的概念,他的sequence number和acknowledge number是TCP基于流的协议的支撑。

仔细观察TCP segment中的内容。可以看到TCP payload部分有frame的排序,在服务器向客户端发送的响应报文中有该响应包含的TCP frame的序列号,具体的原理还需要研究下TCP协议,这里暂时就不说了。
3. 四次挥手
在服务器端发送完响应之后,可以看到客户端向服务器端发送结束会话报文,FIN=1,意思就是“我没有数据要发送了”,这时客户端进入FIN_WAIT_1的状态。而服务端收到这个FIN报文之后呢,会回复一个ACK报文,意在告诉客户端FIN报文收到,这个时候服务端还可以继续向客户端发送数据,客户端进入FIN_WAIT_2的状态。直到服务端数据发送完毕,向客户端发送FIN报文,进入CLOSE_WAIT状态。客户端接收FIN报文,发送ACK,进入TIME_WAIT状态,此时如果服务端没有收到ACK可重复发送。服务器端收到ACK之后,就断开链接,宣告CLOSED。客户端等到2MSL之后没有得到回复,证明服务器端已经正常关闭,此时客户端也宣告CLOSED。至此,TCP的连接才会关闭。
不得不说,这个泪眼朦胧的挥手真的有点复杂与墨迹。却是在网络是不可靠的假定的基础上的最优解。
通过这次的抓包分析,对网络协议的了解深入了一点。明确了网络七层的结构,每层在http的请求中涉及的协议与传输方式。下一次呢,想做点socket边城之类的东西,去了解下传输层信息传递的方式。相信会很有意思的。




