四,TCP/IP协议
浏览器通过HTTP协议向服务器发起请求获取数据,保证了服务器上的页面文件能完整的到达客户端浏览器上,在如此错综复杂的万维网上,HTTP协议是如何保证不丢包,丢包数据重传的呢?这是因为HTTP底层是依靠TCP/IP协议进行传输数据的,TCP/IP协议在客户端与服务器之间建立了稳定的连接,并能再丢包之后进行数据包重传,虽然牺牲了时间,但是带来的收益却是很值得的。
HTTP协议是应用层的协议,规定了数据的内容格式,TCP/IP协议是运输层的协议,规定了数据传输和连接的方式。
?? 那浏览器是如何发送请求给服务器,服务器又是如何返回数据的呢?
浏览器方:
- 应用层按照Http协议,构建HTTP请求报文,将其交给运输层处理。
- 运输层给http请求报文添加 TCP 首部,使之成为 TCP报文段,交给网络层处理。
- 网络层给TCP报文段添加IP首部,使之成为 IP数据包,交给数据链路层处理。
- 数据链路层给该IP数据包添加首部和尾部使之成为帧,交给物理层处理。
- 物理层将帧看为比特流,添加前导码,并将其转换为相应的信号发送到路由器
路由器:
- 物理层得到信号,转化为比特流,去掉前导码转为帧,交给数据链路层。
- 数据链路层得到帧,去掉头部和尾部转为IP数据报,交给网络层。
- 网络层得到IP数据包,从中提取出目的网络地址,查找自身路由表,确定转发端口,再一层一层包装下去给路由器的物理层传输
web服务器方:
- 数据到达物理层,去掉前导码转为帧,交给数据链路层。
- …
- 应用层得到HTTP请求报文,构建HTTP响应报文,后面的步骤就和浏览器层层包装的步骤一样。
流程图:
🔑 TCP/IP 协议
TCP报文段首部格式
-
源端口/目的端口字段:用来写入源端口(标识发送该TCP报文段的应用进程)和目的端口(标识接收该TCP报文段的应用进程)。 -
序号(seq)字段:该字段表示本报文段发送的数据的第一个字节的序号(数据报文中的每个字节都有序号)。 -
确认号(ack)字段:期望收到对方下一个TCP报文段数据的第第一个字节的序号,也是对之前收到的所有数据的确认(若确认号=100,则说明到序号99为止的数据都已接收,下一个想要接收数据的序号为100)。 -
数据偏移字段:指出了TCP报文段的首部长度。 -
保留字段:保留为今后使用。 -
窗口字段:发送本报文段的接收窗口 -
校验和字段:检测数据出出错。 -
6个标志位:
-
确认标志位(ACK): 该字段的值为1时,确认号字段才有效。 取值为0时,确认号字段无效。(TCP规定,在连接建立后所有的TCP报文段的ACK标志位都必须设置为1)。 -
同步标志位(SYN):在 TCP 连接建立是用来同步的序号(三次握手)。TCP 规定 SYN 设置为 1 的报文段不能携带数据。 -
终止标志位(FIN):用来释放 TCP 连接(四次挥手)。 -
复位标志位(RST):用来复位 TCP 连接,当TCP连接出现异常时,需要重新建立连接。 -
推送标志位(PUH):TCP接收方收到该标志位为1时,会尽快将数据报文上交给引用,而不需等待缓存填满。 -
紧急标志位(URG): 该标志位为1时,紧急指针字段才有效。 当发送方有紧急数据时,可将紧急数据直接插到缓存最前面提交给上层,而无需在接收缓存中排队。 比如 TCP 发送方突然中断了 TCP 数据报的发送,这个中断的指令需要立刻让 TCP 接收方知晓。
?? TCP的连接建立-三次握手
三次握手的目的是为了确认双方的接收和发送能力都ok,然后才能进行数据传输的前导工作。
- TCP客户端首先发送一个 TCP 连接请求报文段给 TCP 服务端,并进入同步已发送状态。TCP 连接请求报文段的 SYN 标志位设为1,表明这是一个 TCP 连接请求报文段,序号字段 seq 设置为x,作为 TCP 客户端选择的初始序号。
- TCP服务端若同意TCP客户端的连接请求,向TCP客户端发送一个TCP连接请求确认报文段,进入同步已接收状态。该报文的 同步标志位SYN 和 确认标志位ACK 都设置为1,表明这是一个TCP连接请求确认报文段。序号字段seq由TCP服务器自行选定,确认号字段ack 的值设为 x + 1 ,这是对TCP客户端选择的初始序号的确认。
- TCP客户端在接收TCP服务端的连接请求确认报文段后,需要再向TCP服务器发送一个普通的TCP确认报文段,表明已进入连接已建立状态。该报文段的确认位ACK被设置为1,表明这是一个普通的TCP确认报文段,序号字段seq设置为x+1,这是因为TCP连接请求报文段消耗了一个序号x,我们这里要使用写一个序号x+1,确认号字段ack设置为y+1,这是对TCP服务器的连接请求确认报文段选择的序号的确认。(第三次握手可以携带数据也可以不消耗数据,如果不携带数据,则不消耗序号,下一个报文段的序号仍然是 x + 1)
💡 思考:TCP建立连接能采用两次握手吗?两次是不行,请看下面的图。
?? TCP的连接建立-四次挥手
- TCP客户端首先发送一个连接释放报文,进入终止等待状态1。TCP连接释放报文的终止标志位FIN置为1,确认标志位ACK置为1表明这是一个终止连接的TCP报文,seq序号字段的值为TCP客户进程之前已传送过的数据的最后一个字节的序号加1,ack确认字段的值为TCP客户进程之前已收到的数据最后一个字节的序号+1。
- TCP服务端同意释放TCP连接,发送普通的TCP确认报文段,进入关闭等待状态。seq序号字段的值为TCP客户进程的确认位值,ack确认字段的值为TCP客户端进程序号+1
- 等到TCP服务器进程把剩余数据发送完,TCP服务进程向TCP客户进程发送链接释放报文,进入最后确认状态。TCP连接释放报文的终止标志位FIN置为1,确认标志位ACK置为1表明这是一个终止连接的TCP报文,同时也对之前收到的报文段进行确认。
- TCP客户端收到链接释放报文段,最后向TCP服务端发送一个普通的TCP确认报文段,进入2MSL(MSL一般为2分钟)的最后等待时间
💡 TCP客户端最后2MSL等待的原因
如果TCP客户端发送完最后一个TCP确认报文之后马上关闭,期间发生了该TCP确认报文因为丢失的原因并没有发送到TCP服务端上,会导致TCP服务端会一直发送TCP释放连接的报文,但是此时TCP客户端已经关闭了,根本不会应答TCP服务端,白白让费TCP服务端上的资源。2MSL的一般时间为2分钟,应用可以自行确认更短的时间。
|