基础
说下计算机网络体系结构
计算机网络体系结构,一般有三种:OSI 七层模型、TCP/IP 四层模型五层结构。
简单说,OSI是一个理论上的网络通信模型,TCP/IP是实际上的网络通信模型,五层结构就是为了介绍网络原理而折中的网络通信模型。
OSI 七层模型
OSI 七层模型是国际标准化组织(International Organization for Standardization)制定的一个用于计算机或通信系统间互联的标准体系。
应用层:通过应用进程之间的交互来完成特定网络应用,应用层协议定义的是应用进程间通信和交互的规则,常见的协议有: HTTP FTP SMTP SNMP DNS .
表示层:数据的表示、安全、压缩。确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。
会话层:建立、管理、终止会话,是用户应用程序和网络之间的接口。
运输层:提供源端与目的端之间提供可靠的透明数据传输,传输层协议为不同主机上运行的进程提供逻辑通信。
网络层:将网络地址翻译成对应的物理地址,实现不同网络之间的路径选择, 协议有 ICMP IGMP IP 等 .
数据链路层:在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路。
物理层:建立、维护、断开物理连接。
TCP/IP 四层模型
应用层:对应于 OSI 参考模型的(应用层、表示层、会话层)。
传输层: 对应 OSI 的传输层,为应用层实体提供端到端的通信功能,保证了数据包的顺序传送及数据的完整性。
网际层:对应于 OSI 参考模型的网络层,主要解决主机到主机的通信问题。
网络接口层:与 OSI 参考模型的数据链路层、物理层对应。
五层体系结构
应用层:对应于 OSI 参考模型的(应用层、表示层、会话层)。
传输层:对应 OSI 参考模型的的传输层
网络层:对应 OSI 参考模型的的网络层
数据链路层:对应 OSI 参考模型的的数据链路层
物理层:对应 OSI 参考模型的的物理层
说一下每一层对应的网络协议有哪些?
那么数据在各层之间是怎么传输的呢?
对于发送方而言,从上层到下层层层包装,对于接收方而言,从下层到上层,层层解开包装。
发送方的应用进程向接收方的应用进程传送数据
AP先将数据交给本主机的应用层,应用层加上本层的控制信息H5就变成了下一层的数据单元
传输层收到这个数据单元后,加上本层的控制信息H4,再交给网络层,成为网络层的数据单元
到了数据链路层,控制信息被分成两部分,分别加到本层数据单元的首部(H2)和尾部(T2)
最后的物理层,进行比特流的传输
这个过程类似写信,写一封信,每到一层,就加一个信封,写一些地址的信息。到了目的地之后,又一层层解封,传向下一个目的地。
网络综合
从浏览器地址栏输入 url 到显示主页的过程?
DNS 解析:将域名解析成对应的 IP 地址。
TCP连接:与服务器通过三次握手,建立 TCP 连接
向服务器发送 HTTP 请求
服务器处理请求,返回HTTp响应
浏览器解析并渲染页面
断开连接:TCP 四次挥手,连接结束
我们以输入www.baidu.com 为例:
各个过程都使用了哪些协议?
说说 DNS 的解析过程?
DNS,英文全称是 domain name system,域名解析系统,它的作用也很明确,就是域名和 IP 相互映射。
DNS 的解析过程如下图:
假设你要查询 www.baidu.com 的 IP 地址:
首先会查找浏览器的缓存,看看是否能找到 www.baidu.com 对应的IP地址,找到就直接返回;否则进行下一步。
将请求发往给本地DNS服务器,如果查找到也直接返回,否则继续进行下一步;
本地DNS服务器向 根域名服务器 发送请求,根域名服务器返回负责 com 的顶级域名服务器的IP地址的列表。
本地DNS服务器再向其中一个负责 com 的顶级域名服务器发送一个请求,返回负责 baidu.com 的权限域名服务器的IP地址列表。
本地DNS服务器再向其中一个权限域名服务器发送一个请求,返回 www.baidu.com 所对应的IP地址。
说说 WebSocket 与 Socket 的区别?
Socket 其实就是等于 IP 地址 + 端口 + 协议 。
具体来说,Socket 是一套标准,它完成了对 TCP/IP 的高度封装,屏蔽网络细节,以方便开发者更好地进行网络编程。
WebSocket 是一个持久化的协议,它是伴随 H5 而出的协议,用来解决 http 不支持持久化连接 的问题。
Socket 一个是 网编编程的标准接口 ,而 WebSocket 则是应用层通信协议。
说一下你了解的端口及对应的服务?
端口 | 服务 |
---|---|
21 | FTP(文件传输协议) |
22 | SSH |
23 | Telnet(远程登录服务) |
53 | DNS域名解析服务 |
80 | HTTP超文本传输协议 |
443 | HTTPS |
1080 | Sockets |
3306 | MySQL默认端口号 |
HTTP
说说 HTTP 常用的状态码及其含义?
HTTP状态码首先应该知道个大概的分类:
1XX:信息性状态码
2XX:成功状态码
3XX:重定向状态码
4XX:客户端错误状态码
5XX:服务端错误状态码
HTTP 有哪些请求方式?
说⼀下 GET 和 POST 的区别?
从 HTTP 报文层面来看,GET 请求将信息放在 URL,POST 将请求信息放在请求体中。这一点使得 GET 请求携带的数据量有限,因为 URL 本身是有长度限制的,而 POST 请求的数据存放在报文体中,因此对大小没有限制。而且从形式上看,GET 请求把数据放 URL 上不太安全,而 POST 请求把数据放在请求体里想比较而言安全一些。
从数据库层面来看,GET 符合幂等性和安全性,而 POST 请求不符合。这个其实和 GET/POST 请求的作用有关。按照 HTTP 的约定,GET 请求用于查看信息,不会改变服务器上的信息;而 POST 请求用来改变服务器上的信息。正因为GET 请求只查看信息,不改变信息,对数据库的一次或多次操作获得的结果是一致的,认为它符合幂等性。安全性是指对数据库操作没有改变数据库中的数据。
从其他层面来看,GET 请求能够被缓存,GET 请求能够保存在浏览器的浏览记录里,GET 请求的 URL 能够保存为浏览器书签。这些都是 POST 请求所不具备的。缓存是 GET 请求被广泛应用的根本,他能够被缓存也是因为它的幂等性和安全性,除了返回结果没有其他多余的动作,因此绝大部分的 GET 请求都被CDN 缓存起来了,大大减少了 Web 服务器的负担。
GET 的长度限制是多少?
HTTP中的GET方法是通过URL传递数据的,但是URL本身其实并没有对数据的长度进行限制,真正限制GET长度的是浏览器。
例如IE浏览器对URL的最大限制是2000多个字符,大概2kb左右,像Chrome、Firefox等浏览器支持的URL字符数更多,其中FireFox中URL的最大长度限制是65536个字符,Chrome则是8182个字符。
这个长度限制也不是针对数据部分,而是针对整个URL。
HTTP 请求的过程与原理?
HTTP协议定义了浏览器怎么向服务器请求文档,以及服务器怎么把文档传给浏览器。
每个服务器都有一个进程,它不断监听TCP的端口80,以便发现是否有浏览器向它发出连接建立请求
监听到连接请求,就会建立TCP连接
浏览器向服务器发出浏览某个页面的请求,服务器接着就返回所请求的页面作为响应
最后,释放TCP连接
在浏览器和服务器之间的请求和响应的交互,必须按照规定的格式和遵循一定的规则,这些格式和规则就是超文本传输协议HTTP。
说一下HTTP的报文结构
HTTP报文有两种,HTTP请求报文和HTTP响应报文:
HTTP请求报文
HTTP 请求报文的格式如下:
1 | GET / HTTP/1.1 |
HTTP 请求报文的第一行叫做请求行,后面的行叫做首部行,首部行后还可以跟一个实体主体。请求首部之后有一个空行,这个空行不能省略,它用来划分首部与实体。
请求行包含三个字段:
方法字段:包括POST、GET等请方法。
URL 字段
HTTP 版本字段。
HTTP 响应报文
HTTP 响应报文的格式如下:
1 | HTTP/1.0 200 OK |
HTTP 响应报文的第一行叫做状态行,后面的行是首部行,最后是实体主体。
状态行包含了三个字段:协议版本字段、状态码和相应的状态信息。
实体部分是报文的主要部分,它包含了所请求的对象。
首部行首部可以分为四种首部,请求首部、响应首部、通用首部和实体首部。通用首部和实体首部在请求报文和响应报文中都可以设置,区别在于请求首部和响应首部。
- 常见的请求首部有 Accept 可接收媒体资源的类型、Accept-Charset 可接收的字符集、Host 请求的主机名。
- 常见的响应首部有 ETag 资源的匹配信息,Location 客户端重定向的 URI。
- 常见的通用首部有 Cache-Control 控制缓存策略、Connection 管理持久连接。
- 常见的实体首部有 Content-Length 实体主体的大小、Expires 实体主体的过期时间、Last-Modified 资源的最后修改时间。
URI 和 URL 有什么区别?
URI,统一资源标识符(Uniform Resource Identifier, URI),标识的是Web上每一种可用的资源,如 HTML文档、图像、视频片段、程序等都是由一个URI进行标识的。
URL,统一资源定位符(Uniform Resource Location),它是URI的一种子集,主
要作用是提供资源的路径。URL告诉我们资源在互联网上的具体位置,比如网页的网址、图片的链接等等。它通常由协议(比如HTTP或HTTPS)、域名(比如www.example.com)和路径(比如/page)组成。
说下 HTTP/1.0,1.1,2.0 的区别?
关键需要记住 HTTP/1.0 默认是短连接,可以强制开启,HTTP/1.1 默认长连接,HTTP/2.0 采用多路复用。
HTTP/1.0
默认使用 短连接 ,每次请求都需要建立一个 TCP 连接。它可以设置 Connection: keep-alive
这个字段,强制开启长连接。
HTTP/1.1
引入了持久连接,即 TCP 连接默认不关闭,可以被多个请求复用。
分块传输编码,即服务端每产生一块数据,就发送一块,用” 流模式” 取代” 缓存模式”。
管道机制,即在同一个 TCP 连接里面,客户端可以同时发送多个请求。
HTTP/2.0
二进制协议,1.1 版本的头信息是文本(ASCII 编码),数据体可以是文本或者二进制;2.0 中,头信息和数据体都是二进制。
完全多路复用,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应。
报头压缩,HTTP 协议不带有状态,每次请求都必须附上所有信息。Http/2.0 引入了头信息压缩机制,使用 gzip 或 compress 压缩后再发送。
服务端推送,允许服务器未经请求,主动向客户端发送资源。
HTTP/3了解吗?
HTTP/3主要有两大变化,传输层基于UDP、使用QUIC保证UDP可靠性。
HTTP/2存在的一些问题,比如重传等等,都是由于TCP本身的特性导致的,所以HTTP/3在QUIC的基础上进行发展而来,QUIC(Quick UDP Connections)直译为快速UDP网络连接,底层使用UDP进行数据传输。
HTTP/3主要有这些特点:
使用UDP作为传输层进行通信
在UDP的基础上QUIC协议保证了HTTP/3的安全性,在传输的过程中就完成了TLS加密握手
HTTPS 要建⽴⼀个连接,要花费 6 次交互,先是建⽴三次握⼿,然后是 TLS/1.3的三次握⼿。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 3 次,减少了交互次数。
QUIC 有⾃⼰的⼀套机制可以保证传输的可靠性的。当某个流发⽣丢包时,只会阻塞这个流,其他流不会受到影响。
我们拿一张图看一下HTTP协议的变迁:
HTTP 如何实现长连接?在什么时候会超时?
什么是 HTTP 的长连接?
- HTTP 分为长连接和短连接, 本质上说的是 TCP 的长短连接 。TCP 连接是一个双向的通道,它是可以保持一段时间不关闭的,因此 TCP 连接才具有真正的长连接和短连接这一说法。
- TCP 长连接可以复用一个 TCP 连接,来发起多次的 HTTP 请求,这样就可以减少资源消耗,比如一次请求 HTML,如果是短连接的话,可能还需要请求后续的JS/CSS。
如何设置长连接?
通过在头部(请求和响应头)设置 Connection 字段指定为 keep-alive ,HTTP/1.0协议支持,但是是默认关闭的,从 HTTP/1.1 以后,连接默认都是长连接。
在什么时候会超时呢?
HTTP 一般会有 httpd 守护进程,里面可以设置 keep-alive timeout ,当 tcp 连接闲置超过这个时间就会关闭,也可以在 HTTP 的 header 里面设置超时时间
TCP 的 keep-alive 包含三个参数,支持在系统内核的 net.ipv4 里面设置;当TCP 连接之后,闲置了 tcp_keepalive_time ,则会发生侦测包,如果没有收到对方的 ACK,那么会每隔 tcp_keepalive_intvl 再发一次,直到发送了tcp_keepalive_probes ,就会丢弃该连接。
1 | 1. tcp_keepalive_intvl = 15 |
说说HTTP 与 HTTPS 有哪些区别?
HTTP 是超⽂本传输协议,信息是明⽂传输,存在安全⻛险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在TCP 和 HTTP ⽹络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输。
HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。⽽HTTPS 在 TCP 三次握⼿之后,还需进⾏ SSL/TLS 的握⼿过程,才可进⼊加密报⽂传输。
HTTP 的端⼝号是 80,HTTPS 的端⼝号是 443。
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
为什么要用HTTPS?解决了哪些问题?
因为HTTP 是明⽂传输,存在安全上的风险:
窃听风险,⽐如通信链路上可以获取通信内容,用户账号被盗。
篡改风险,⽐如强制植⼊垃圾⼴告,视觉污染。
冒充风险,比如冒充淘宝网站,用户金钱损失。
所以引入了HTTPS,HTTPS 在 HTTP 与 TCP 层之间加⼊了 SSL/TLS 协议,可以很好的解决了这些风险:
信息加密 :交互信息⽆法被窃取。
校验机制 :⽆法篡改通信内容,篡改了就不能正常显示。
身份证书 :能证明淘宝是真淘宝。
所以SSL/TLS 协议是能保证通信是安全的。
HTTPS工作流程是怎样的?
要点:公私钥、数字证书、加密、对称加密、非对称加密。
HTTPS 主要工作流程:
客户端发起 HTTPS 请求,连接到服务端的 443 端口。
服务端有一套数字证书(证书内容有公钥、证书颁发机构、失效日期等)。
服务端将自己的数字证书发送给客户端(公钥在证书里面,私钥由服务器持有)。
客户端收到数字证书之后,会验证证书的合法性。如果证书验证通过,就会生成一个随机的对称密钥,用证书的公钥加密。
客户端将公钥加密后的密钥发送到服务器。
服务器接收到客户端发来的密文密钥之后,用自己之前保留的私钥对其进行非对称解密,解密之后就得到客户端的密钥,然后用客户端密钥对返回数据进行对称加密,酱紫传输的数据都是密文啦。
服务器将加密后的密文返回到客户端。
客户端收到后,用自己的密钥对其进行对称解密,得到服务器返回的数据。
客户端怎么去校验证书的合法性?
首先,服务端的证书从哪来的呢?
为了让服务端的公钥被⼤家信任,服务端的证书都是由 CA (Certificate Authority,证书认证机构)签名的,CA就是⽹络世界⾥的公安局、公证中⼼,具有极⾼的可信度,所以由它来给各个公钥签名,信任的⼀⽅签发的证书,那必然证书也是被信任的。
CA 签发证书的过程,如上图左边部分:
⾸先 CA 会把持有者的公钥、⽤途、颁发者、有效时间等信息打成⼀个包,然后对这些信息进⾏ Hash 计算,得到⼀个 Hash 值;
然后 CA 会使⽤⾃⼰的私钥将该 Hash 值加密,⽣成 Certificate Signature,也就是CA 对证书做了签名;
最后将 Certificate Signature 添加在⽂件证书上,形成数字证书;
客户端校验服务端的数字证书的过程,如上图右边部分:
⾸先客户端会使⽤同样的 Hash 算法获取该证书的 Hash 值 H1;
通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使⽤CA 的公钥解密 Certificate
Signature 内容,得到⼀个 Hash 值 H2 ;
最后⽐较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。
假如在HTTPS的通信过程中,中间人篡改了证书原文,由于他没有CA机构的私钥,所以CA公钥解密的内容就不一致。
如何理解 HTTP 协议是无状态的?
这个 无状态 的的 状态 值的是什么?是客户端的状态,所以字面意思,就是HTTP协议中服务端不会保存客户端的任何信息。
比如当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。
那有什么办法记录状态呢?
主要有两个办法,Session和Cookie。
说说Session 和 Cookie 有什么联系和区别?
先来看看什么是 Session 和 Cookie :
Cookie 是保存在客户端的一小块文本串的数据。客户端向服务器发起请求时,服务端会向客户端发送一个 Cookie,客户端就把 Cookie 保存起来。在客户端下次向同一服务器再发起请求时,Cookie 被携带发送到服务器。服务端可以根据这个Cookie判断用户的身份和状态。
Session 指的就是服务器和客户端一次会话的过程。它是另一种记录客户状态的机制。不同的是cookie保存在客户端浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该session中查找用户的状态。
Session 和 Cookie 到底有什么不同呢?
存储位置不一样,Cookie 保存在客户端,Session 保存在服务器端。
存储数据类型不一样,Cookie 只能保存ASCII,Session可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般有效时间较短,客户端关闭或者 Session 超时都会失效。
隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
存储大小不同, 单个Cookie保存的数据不能超过4K,Session可存储数据远高于Cookie。
Session 和 Cookie有什么关联呢?
可以使用Cookie记录Session的标识。
用户第一次请求服务器时,服务器根据用户提交的信息,创建对应的 Session,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入 Cookie 中,同时 Cookie 记录此 SessionID 是属于哪个域名。
当用户第二次访问服务器时,请求会自动判断此域名下是否存在 Cookie 信息,如果存在,则自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到,说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
分布式环境下Session怎么处理呢?
分布式环境下,客户端请求经过负载均衡,可能会分配到不同的服务器上,假如一个用户的请求两次没有落到同一台服务器上,那么在新的服务器上就没有记录用户状态的Session。
这时候怎么办呢?
可以使用Redis等分布式缓存来存储Session,在多台服务器之间共享。
客户端无法使用Cookie怎么办?
有可能客户端无法使用Cookie,比如浏览器禁用Cookie,或者客户端是安卓、IOS等等。
这时候怎么办?SessionID怎么存?怎么传给服务端呢?
首先是SessionID的存储,可以使用客户端的本地存储,比如浏览器的sessionStorage。
接下来怎么传呢?
拼接到URL里:直接把SessionID作为URL的请求参数
放到请求头里:把SessionID放到请求的Header里,比较常用。
TCP
详细说一下 TCP 的三次握手机制
TCP提供面向连接的服务,在传送数据前必须建立连接,TCP连接是通过三次握手建立的。
三次握手的过程:
最开始,客户端和服务端都处于CLOSE状态,服务端监听客户端的请求,进入LISTEN状态
客户端端发送连接请求, 第一次握手 (SYN=1, seq=x),发送完毕后,客户端就进入 SYN_SENT 状态
服务端确认连接, 第二次握手 (SYN=1, ACK=1, seq=y, ACKnum=x+1), 发送完毕后,服务器端就进入 SYN_RCV 状态。
客户端收到服务端的确认之后,再次向服务端确认,这就是 第三次握手(ACK=1,ACKnum=y+1),发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态。
TCP 握手为什么是三次,为什么不能是两次?不能是四次?
为什么不能是两次?
为了防止服务器端开启一些无用的连接增加服务器开销
防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中,比如客户端发起了 SYN=1 的第一次握手。
如果服务器端就直接创建了这个连接并返回包含 SYN、ACK 和 Seq 等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包。
如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,服务器端是不知道客户端有没有接收到服务器端返回的信息的。
服务端就认为这个连接是可用的,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。这样一来,就会有很多无效的连接端口白白地开着,导致资源的浪费。
还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。
所以我们需要“第三次握手”来确认这个过程:
通过第三次握手的数据告诉服务端,客户端有没有收到服务器“第二次握手”时传过去的数据,以及这个连接的序号是不是有效的。若发送的这个数据是“ 收到且没有问题 ”的信息,接收后服务器就正常建立 TCP 连接,否则建立 TCP 连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。
为什么不是四次?
简单说,就是三次挥手已经足够创建可靠的连接,没有必要再多一次握手导致花费更多的时间建立连接。
三次握手中每一次没收到报文会发生什么情况?
第一次握手服务端未收到SYN报文
服务端不会进行任何的动作,而客户端由于一段时间内没有收到服务端发来的确
认报文,等待一段时间后会重新发送SYN报文,如果仍然没有回应,会重复这个
过程,直到发送次数超过最大重传次数限制,就会返回连接建立失败。
第二次握手客户端未收到服务端响应的ACK报文
客户端会继续重传,直到次数限制;而服务端此时会阻塞在accept()处,等待客户端发送ACK报文
第三次握手服务端为收到客户端发送过来的ACK报文
服务端同样会采用类似客户端的超时重传机制,如果重试次数超过限制,则accept()调用返回-1,服务端建立连接失败;而此时客户端认为自己已经建立连接成功,因此开始向服务端发送数据,但是服务端的accept()系统调用已经返回,此时不在监听状态,因此服务端接收到客户端发送来的数据时会发送RST报文给客户端,消除客户端单方面建立连接的状态。
第二次握手传回了 ACK,为什么还要传回 SYN?
ACK是为了告诉客户端传来的数据已经接收无误。
而传回SYN是为了告诉客户端,服务端响应的确实是客户端发送的报文。
第3次握手可以携带数据吗?
第3次握手是可以携带数据的。
此时客户端已经处于ESTABLISHED状态。对于客户端来说,它已经建立连接成功,并且确认服务端的接收和发送能力是正常的。
第一次握手不能携带数据是出于安全的考虑,因为如果允许携带数据,攻击者每次在SYN报文中携带大量数据,就会导致服务端消耗更多的时间和空间去处理这些报文,会造成CPU和内存的消耗。
说说半连接队列和 SYN Flood 攻击的关系?
什么是半连接队列?
TCP 进入三次握手前,服务端会从 CLOSED 状态变为 LISTEN 状态, 同时在内部创建了两个队列:半连接队列(SYN 队列)和全连接队列(ACCEPT 队列)。
顾名思义,半连接队列存放的是三次握手未完成的连接,全连接队列存放的是完成三次握手的连接。
TCP 三次握手时,客户端发送 SYN 到服务端,服务端收到之后,便回复 ACK和 SYN ,状态由 LISTEN 变为 SYN_RCVD ,此时这个连接就被推入了 SYN队列 ,即半连接队列。
当客户端回复 ACK, 服务端接收后,三次握手就完成了。这时连接会等待被具体的应用取走,在被取走之前,它被推入 ACCEPT 队列,即全连接队列。
什么是SYN Flood ?
SYN Flood 是一种典型的 DDos 攻击,它在短时间内,伪造不存在的 IP 地址, 向服务器发送大量SYN 报文。当服务器回复 SYN+ACK 报文后,不会收到 ACK 回应报文,那么SYN队列里的连接旧不会出对队,久⽽久之就会占满服务端的 SYN 接收队列(半连接队列),使得服务器不能为正常⽤户服务。
那有什么应对方案呢?
主要有 syn cookie 和 SYN Proxy 防火墙等。
syn cookie :在收到 SYN 包后,服务器根据一定的方法,以数据包的源地址、端口等信息为参数计算出一个 cookie 值作为自己的 SYNACK 包的序列号,回复SYN+ACK 后,服务器并不立即分配资源进行处理,等收到发送方的 ACK 包后,重新根据数据包的源地址、端口计算该包中的确认序列号是否正确,如果正确则建立连接,否则丢弃该包。
SYN Proxy 防火墙 :服务器防火墙会对收到的每一个 SYN 报文进行代理和回应,并保持半连接。等发送方将 ACK 包返回后,再重新构造 SYN 包发到服务器,建立真正的 TCP 连接。
说说 TCP 四次挥手的过程?
TCP 四次挥手过程:
数据传输结束之后,通信双方都可以主动发起断开连接请求,这里假定客户端发起
客户端发送释放连接报文, 第一次挥手 (FIN=1,seq=u),发送完毕后,客户端进入 FIN_WAIT_1 状态。
服务端发送确认报文, 第二次挥手 (ACK=1,ack=u+1,seq =v),发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入FIN_WAIT_2 状态。
服务端发送释放连接报文, 第三次挥手 (FIN=1,ACK1,seq=w,ack=u+1),发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
客户端发送确认报文, 第四次挥手 (ACK=1,seq=u+1,ack=w+1),客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态, 等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后 ,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
TCP 挥手为什么需要四次呢?
再来回顾下四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。
关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
服务端收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
TCP 四次挥手过程中,为什么需要等待 2MSL, 才进入 CLOSED关闭状态?
为什么需要等待?
为了保证客户端发送的最后一个 ACK 报文段能够到达服务端。 这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的服务端就收不到对已发送的 FIN + ACK 报文段的确认。服务端会超时重传这个 FIN+ACK 报文段,而客户端就能在2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着客户端重传一次确认,重新启动 2MSL 计时器。最后,客户端和服务器都正常进入到CLOSED 状态。
防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。
为什么等待的时间是2MSL?
MSL 是 Maximum Segment Lifetime,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。
TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是: ⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间。
⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时重发 Fin报⽂,另⼀⽅接收到 FIN 后,会重发 ACK 给被动关闭⽅, ⼀来⼀去正好 2 个MSL。
保活计时器有什么用?
除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer)。
设想这样的场景:客户已主动与服务器建立了 TCP 连接。但后来客户端的主机突然发生故障。显然,服务器以后就不能再收到客户端发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就需要使用保活计时器了。
服务器每收到一次客户端的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若连续发送 10 个探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接。
CLOSE-WAIT 和 TIME-WAIT 的状态和意义?
CLOSE-WAIT状态有什么意义?
服务端收到客户端关闭连接的请求并确认之后,就会进入CLOSE-WAIT状态。此时服务端可能还有一些数据没有传输完成,因此不能立即关闭连接,而CLOSE-WAIT状态就是为了保证服务端在关闭连接之前将待发送的数据处理完。
TIME-WAIT有什么意义?
TIME-WAIT状态发生在第四次挥手,当客户端向服务端发送ACK确认报文后进入TIME-WAIT状态。
它存在的意义主要是两个:
- 防⽌旧连接的数据包
如果客户端收到服务端的FIN报文之后立即关闭连接,但是此时服务端对应的端口并没有关闭,如果客户端在相同端口建立新的连接,可能会导致新连接收到旧连接残留的数据包,导致不可预料的异常发生。
- 保证连接正确关闭
假设客户端最后一次发送的ACK包在传输的时候丢失了,由于TCP协议的超时重传机制,服务端将重发FIN报文,如果客户端没有维持TIME-WAIT状态而直接关闭的话,当收到服务端重新发送的FIN包时,客户端就会使用RST包来响应服务端,导致服务端以为有错误发生,然而实际关闭连接过程是正常的。