当客户端要服务器断开连接时,客户端 TCP 会向服务器发送一个特殊的报文段,该报文段的 FIN 标志位会被置 1,接着服务器会向客户端发送一个确认报文段。然后服务器也会客户端发送一个 FIN 标志位为 1 的终止报文段,随后客户端回送一个确认报文段,服务器立即断开连接。客户端等待一段时间后也断开连接。
个人觉得这个问题还可以扩展一下,试想一下在键入 URL 之前,也就是刚开完机的时候,需要联网,然后才能上网。这个阶段包括了获取本机 IP 地址,获取 DNS 服务器 IP 地址,获得网关路由器 IP 和 MAC 地址等操作,把这些一起答上去会不会好一些?以下是回答:
获取本机 IP 地址,DNS 服务器地址,网关路由器地址
首先我们需要准备一个 DHCP 报文,封装在一个 UDP 报文段中,里面包括本机端口号 68 和目的端口号 67,然后到网络层封装成数据包里面包括了本机的初始 IP 0.0.0.0,和广播地址 255.255.255.255。接着到链路层封装成链路层帧。里面包括广播地址和本机网卡的 MAC 地址。最后发送到本地局域网中
这个数据包最终会被局域网中的 DHCP 服务器发现(有可能有多个 DHCP 服务器),DHCP 服务器会把可用的 IP 地址返回给我们的主机。然后操作系统选择一个 IP 地址并发送给 DHCP 服务器,最后 DHCP 服务器会返回一个包含本机 IP,DNS 服务器 IP,网关路由器 IP 的报文。
接下来我们需要通过网关路由器的 IP 地址去获得网关路由器的 MAC 地址,这样我们才可以把获取网站 IP 的 DNS 请求报文由网关发送给 DNS 服务器。这时候我们需要准备一个 ARP 请求报文,请求获取网关路由器的 MAC 地址,这个报文同样是以广播的方式发送到局域网中,网关路由器接受到请求报文就会把自己的 MAC 地址返回给本机。
获取域名的 IP 地址
接下来一切都准备好了,可以开始讲键入 URL 之后的事情了:
首先我们要访问 DNS 服务器获得网站对应的 IP 地址,这时我们需要把 DNS 报文封装到一个 UDP 报文中,进而封装到网络层的数据包中,填上源 IP,目的 DNS 服务器 IP 地址。接着封装链路层,填上网卡 MAC 地址和网关路由器 MAC 地址。接下来这个 DNS 请求报文就会经网关路由器发送给 DNS 服务器。
我们假设 DNS 服务器缓存有该网站的 IP 地址,(如果没有缓存会进一步向更高级的DNS服务器索要IP地址)。接着 DNS 服务器会返回该域名的 IP 地址。
三次握手建立 TCP 连接
拿到了该网站的 IP 地址后就可以与该网站的服务器建立 TCP 连接了。建立 TCP 连接需要经过三次握手,过程如下:(更详细的过程在开头)
本机的 TCP 首先生成一个不带任何数据,SYN 标志位为 1,序号字段假设为client_num 的 TCP 报文,经过下层一系列网络栈后发送给目的 ip 服务器。
常见状态码:
200 OK:正常返回信息
400 Bad Request:客户端请求有语法错误,不能被服务器所理解
403 Forbidden:服务器收到请求,但是拒绝提供服务
404 Not Found:请求资源不存在,输入了错误的URL
500 Internal Server Error:服务器发生不可预期错误
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
9、GET 请求和 POST 请求的区别
从 HTTP 报文层面来看,GET 请求将信息放在 URL,POST 将请求信息放在请求体中。这一点使得 GET 请求携带的数据量有限,因为 URL 本身是有长度限制的,而 POST 请求的数据存放在报文体中,因此对大小没有限制。而且从形式上看,GET 请求把数据放 URL 上感觉不太安全,而 POST 请求把数据放在请求体里似乎安全一些。实际上想要获取 POST 请求中的内容还是很容易的,因此两者在安全性上其实没有太大差异,想要实现安全的信息传输还是得靠 HTTPS。
从数据库层面来看,GET 符合幂等性和安全性,而 POST 请求不符合。这个其实和 GET/POST 请求的作用有关。按照 HTTP 的约定,GET 请求用于查看信息,不会改变服务器上的信息;而 POST 请求用来改变服务器上的信息。正因为 GET 请求只查看信息,不改变信息,对数据库的一次或多次操作获得的结果是一致的,认为它符合幂等性。安全性是指对数据库操作没有改变数据库中的数据。
从其他层面来看,GET 请求能够被缓存,GET 请求能够保存在浏览器的浏览记录里,GET 请求的 URL 能够保存为浏览器书签。这些都是 POST 请求所不具备的。缓存是 GET 请求被广泛应用的根本,他能够被缓存也是因为它的幂等性和安全性,除了返回结果没有其他多余的动作,因此绝大部分的 GET 请求都被 CDN 缓存起来了,大大减少了 Web 服务器的负担。