计算机网络
-
请详细介绍一下 TCP 的三次握手和四次挥手机制?
客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态 第一次握手 客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。 第二次握手 服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。 第三次握手 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务端的数据,之后客户端处于 established 状态。服务端收到客户端的应答报文后,也进入 established 状态。
第一次挥手 打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。 第二次挥手 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT 状态。 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。 第三次挥手 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。 第四次挥手 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态 服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。
-
为什么建立连接需要三次握手。第三次握手时,发送方可以携带其他数据吗?
三次握手的原因: 三次握手才可以阻止重复历史连接的初始化(主要原因),在两次握手的情况下,服务端没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费。 三次握手才可以同步双方的初始序列号 三次握手才可以避免资源浪费 第三次握手是可以携带数据的,前两次握手是不可以携带数据的
-
为什么需要四次挥手。详细讲讲time_wait和close_wait。
关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。 服务端收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
主动发起关闭连接的一方,才会有 TIME-WAIT 状态: 需要 TIME-WAIT 状态,主要是两个原因: 防止历史连接中的数据,被后面相同四元组的连接错误的接收; 保证「被动关闭连接」的一方,能被正确的关闭;等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。 过多的 TIME-WAIT 状态主要的危害有两种: 第一是占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等; 第二是占用端口资源,端口资源也是有限的,一般可以开启的端口为 32768~61000,也可以通过 net.ipv4.ip_local_port_range参数指定范围。 优化过多的 TIME-WAIT: 打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项:在调用 connect() 函数时,内核会随机找一个 time_wait 状态超过 1 秒的连接给新的连接复用 net.ipv4.tcp_max_tw_buckets:当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将后面的 TIME_WAIT 连接状态重置 程序中使用 SO_LINGER ,应用强制使用 RST 关闭:调用close后,会立该发送一个RST标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭 如果服务端要避免过多的 TIME_WAIT 状态的连接,就永远不要主动断开连接,让客户端去断开,由分布在各处的客户端去承受 TIME_WAIT
CLOSE_WAIT 状态是「被动关闭方」才会有的状态,而且如果「被动关闭方」没有调用 close 函数关闭连接,那么就无法发出 FIN 报文,从而无法使得 CLOSE_WAIT 状态的连接转变为 LAST_ACK 状态。
3.5 为什么 TIME_WAIT 等待的时间是 2MSL?
MSL 与 TTL 的区别: MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。
TTL 的值一般是 64,Linux 将 MSL 设置为 30 秒,意味着 Linux 认为数据报文经过 64 个路由器的时间不会超过 30 秒,如果超过了,就认为报文已经消失在网络中了。
TIME_WAIT 等待 2 倍的 MSL,比较合理的解释是: 网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。
-
SYN超时和洪泛攻击是什么?解决策略有哪些?
在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是: 半连接队列,也称 SYN 队列; 全连接队列,也称 accept 队列; SYN 攻击方式最直接的表现就会把 TCP 半连接队列打满,这样当 TCP 半连接队列满了,后续再在收到 SYN 报文就会丢弃,导致客户端无法和服务端建立连接。
避免 SYN 攻击方式,可以有以下四种方法: 调大 netdev_max_backlog;当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值 增大 TCP 半连接队列; 开启 tcp_syncookies;可以在不使用 SYN 半连接队列的情况下成功建立连接,相当于绕过了 SYN 半连接来建立连接。 减少 SYN+ACK 重传次数
-
TCP和UDP有什么特点,有什么区别?
- TCP面向连接,UDP无连接;
- TCP可靠传输,使用流量控制和拥塞控制,UDP不可靠传输;
- TCP只能一对一通信,UDP支持一对一,一对多,多对多
- TCP面向字节流,UDP面向报文
- TCP首部最小20字节最大60字节,UDP首部仅8字节
- TCP可靠传输的应用,如:文件传输,UDP适用于实时应用,如:IP电话、视频会议、直播
-
在浏览器的地址栏中输入URL,后续的网络都发生了什么,尽可能讲一讲。
- 浏览器对 URL 进行解析之后,确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。
- 浏览器会先看自身有没有对这个域名的缓存,如果有,就直接返回,如果没有,就去问操作系统,操作系统也会去看自己的缓存,如果有,就直接返回,如果没有,再去 hosts 文件看,也没有,才会去问「本地 DNS 服务器」, 还没有会通过DNS查询服务器域名对应的 IP 地址。
- 应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,协议栈的下面一半是用 IP 协议控制网络包收发操作。
- 先查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。而当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询, 网卡驱动程序控制网卡发送数据。
- 数据包抵达服务器后,服务器会先扒开数据包的 MAC 头部,查看是否和服务器自己的 MAC 地址符合,符合就将包收起来。接着继续扒开数据包的 IP 头,发现 IP 地址符合,根据 IP 头中协议项,知道自己上层是 TCP 协议。扒开 TCP 的头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。TCP头部里面还有端口号, HTTP 的服务器正在监听这个端口号。服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。
- 服务器的 HTTP 进程看到,封装响应数据,于是就把这个网页封装在 HTTP 响应报文里。然后数据包也要加上 TCP、IP、MAC 头部,从网卡出去,交由交换机转发到出城的路由器,直到发送给客户端。
-
HTTP和HTTPS有哪些区别?
HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。 HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。 两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。 HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
-
GET和POST有哪些区别?
- get传参方式是通过地址栏URL传递,post传参方式参数URL不可见;
- get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。
- get方法是安全、幂等、可被缓存的。 post没有长度限制
- get后退不会有影响,post后退会重新进行提交
- get请求可以被缓存,post不可以被缓存
- get只支持ASCII字符,post没有字符类型限制 优点: 1.安全性比get传参方式好 2.post没有字符和编码的限制,能发送的数据类型更多· 3.post传送数据没有大小限制,比get可以发送的更多的数据
-
COOKIE和SESSION有什么区别?又有哪些联系?
token:
令牌,是用户身份的验证方式。
最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名)
session:
会话,代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续。
cookie中存放着一个sessionID,请求时会发送这个ID;
session因为请求(request对象)而产生;
session是一个容器,可以存放会话过程中的任何对象;
session的创建与使用总是在服务端,浏览器从来都没有得到过session对象;
session是一种http存储机制,目的是为武装的http提供持久机制。
cookie:
储存在用户本地终端上的数据,服务器生成,发送给浏览器,下次请求统一网站给服务器。Cookie的大小只有4kb,它是一种纯文本文件,每次发起HTTP请求都会携带Cookie。
SessionStorage:
由于SessionStorage具有时效性,所以可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了。
LocalStorage:
存储的信息较大(大小一般为5MB),LocalStorage是持久储存,并不会随着页面的关闭而消失,除非主动清理,不然会永久存在,仅储存在本地,不像Cookie那样每次HTTP请求都会被携,LocalStorage受到同源策略的限制,即端口、协议、主机地址有任何一个不相同,都不会访问。
sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。