차례
머리말
TCP 세 방향 핸드 셰이크 네 파가 매우 두 프로세스 중 하나가 다른 한편으로는,이 두 과정은 실제 사용에 매우 중요하다, 본질적으로 인터뷰의 필수 과목 인 두 가지 문제를 잘 알고 있어야한다.
여기에 단순히이 두 과정 모두 그것에 대해 얼마나 볼 수 있습니다.
데이터 그램 헤더
공정 네 특정 세 방향 핸드 셰이크를 배우고 흔들며하기 전에, 나는 그것이 특정 이해 TCP / IP 데이터 그램 헤더에 먼저 필요하다고 생각 물론, 모든 정보를 알 필요가 없습니다.
IP 데이터 그램 헤더가 수행한다 : 상기 이미지는이 경우에, 우리가 이해할 필요는 IP 데이터 그램 헤더 구조 소스 주소 와 목적지 주소 정보가 충분합니다.
그런 다음 TCP 데이터 그램 헤더 구조는 다음과 같다 :
더 복잡하지만, 여기로 TCP 헤더와 IP 헤더의 구조, 우리는이 정보의 일부에 초점을 맞출 필요가있다 :
TCP 헤더 | 효과 나 의미 |
---|---|
소스 포트 및 대상 포트 | 그리고 IP 헤더의 소스 주소 와 목적지 주소는 고유 각 연결을 식별하여 |
일련 번호 | 즉, 전송 된 바이트 스트림을 식별하는 데 사용됩니다 보낸 각 바이트에 번호가 |
확인 번호 | 전방 서로 전송되는 데이터 패킷의 수신을 확인 송신자, 즉 다음에 수신 된 데이터 패킷의 시퀀스 번호를 확인하고자 |
SYN의 플래그 | 새 연결을 설정할 때이 필드가 활성화되어,이 나타냅니다 전송 시퀀스 번호 의에 초기 시퀀스 번호 |
ACK의 플래그 | 표시 승인 번호 연결이 일반적으로 사용 가능 설정되면 필드는 유효 |
FIN 플래그 | 表明该报文的发送方已经结束向对方发送数据 |
三次握手
在对 TCP/IP 数据报的头部结构有了一定的了解后,就可以进入正题了,首先是三次握手的过程:
三次握手过程的文字描述:
- 第一次握手,客户端向服务端发送数据报,该数据报的 SYN 标志为 1,而序列号的值为 x
- 第二次握手,服务端向客户端发送数据报,该数据报的 SYN 标志和 ACK 标志为 1,而序列号的值为 y,确认号的值为 x + 1
- 第三次握手,客户端向服务端发送数据报,该数据报的 ACK 表示为 1,而序列号的值为 x + 1,确认号的值为 y + 1
这个过程其实不难,但是,更重要的是对这个过程的理解,或者说,就是需要明白:为什么要进行三次握手?
这个问题存在很多种解释,个人感觉最好的一个解释应该是 知乎 上的一个回答,这个回答从三次握手的目的出发对为什么需要三次握手进行了解释:
- 三次握手的目的除了让通信双方了解一个连接正在建立以外,还在于利用数据报的头部交换彼此的 初始序列号
- 当 SYN 标志位 1 时,会表明当前数据报头部的序列号就是 初始序列号
- 第一次握手时,客户端将自身的 初始序列号 发送给了服务端
- 第二次握手时,服务端通过确认号确认了客户端的 初始序列号
- 第二次握手时,服务端将自身的 初始序列号 发送给了客户端
- 第三次握手时,客户端通过确认号确认了服务端的 初始序列号
也就是说,三次握手的过程可以简化为客户端和服务端交换彼此的 初始序列号 的过程,每次交换需要:
- 发送 初始序列号 给另一方
- 接受到另一方的 确认号 表明 初始序列号 已经成功交给另一方
在这个过程中,由于单个数据报可以同时携带确认号、初始序列号,因此,将下面四个过程压缩成了三次握手:
- 客户端 -> 服务端:我的初始序列号为 X
- 服务端 -> 客户端:确认你的初始序列号为 X
- 服务端 -> 客户端:我的初始序列号为 Y
- 客户端 -> 服务端:确认你的初始序列号为 Y
可以看到,这个过程必然是需要三次握手的,少一次显得不够,多一次显得多余。
当然了,还有其他的一些解释,有兴趣的可以看一下参考链接中的文章。
SYN 攻击
SYN 攻击是针对三次握手过程的一种攻击方式,通过观察三次握手的过程可以发现,当服务端向客户端发送 SYN-ACK 后还未进入完整的连接状态,而是处于 半连接 状态。只有在接收到客户端的 ACK 后才会转入完整的连接状态。
而 SYN 攻击便是通过短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包实现的。这使得服务端存在大量未确认的半连接,这些半连接只有等待服务端不断的重发直至超时才会断开。
这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。
四次挥手
四次挥手似乎没有三次握手那么有名,但也还是十分重要的一个过程,其具体过程如下:
四次挥手过程的文字描述:
- 第一次挥手,主动关闭者 A 向被动关闭者 B 发送 FIN 标志为 1 的数据报,并指明希望接收者看到的自己当前的序列号 u
- 第二次挥手,被动关闭者 B 将 u 值加一作为响应的确认号值,表明它已经成功接收到主动关闭者发送的 FIN
- 第三次挥手,被动关闭者 B 将身份转变为主动关闭者,并发送自己的 FIN,并指明希望接收者看到的自己当前的序列号 w
- 第四次挥手,A 将 w 值加一作为响应的确认号值,表明它已经成功接收到 B 发送的 FIN
和三次握手一样,我们需要的是对四次挥手过程的理解,这里就附上个人的理解好了:
- 四次挥手的过程其实就是关闭连接的过程
- 关闭连接的过程中,主动关闭者和被动关闭者需要停止各自的 发送 和 接收 操作
- 任何一端只能主动关闭自身的 发送 操作
- 任何一端只能在确定对方已经停止 发送 操作以后才能停止相应的 接收 操作
也就是说,四次挥手的过程我们可以看成是客户端和服务端停止自身的 发送 操作并 通知 另一端的过程:
- 第一次挥手,主动关闭者通过发送带有 FIN 标志的数据报告诉被动关闭者:我的数据已经发送完了,你可以停止接受操作了
- 第二次挥手,被动关闭者通过发送带有相应确认号的数据报告诉主动关闭者:好的,你的通知我已受到,你可以停止发送操作了
- 第三次和第四次操作正好相反,原本的被动关闭者变为主动关闭者,关闭自身的 发送 操作并通知另一端
由于任何一端停止自身的 发送 操作并 通知 另一端都需要两次挥手的过程,因此,总的来说就需要四次挥手了。
半连接
通过对四次挥手过程的理解我们可以发现,连接的关闭过程是由两端分别停止自身的数据 发送 操作完成的,因此,假如一方停止发送操作,而另一方继续发送数据,这时便进入了半连接状态。
TIME_WAIT
TIME_WAIT 这个状态也是比较常见的一个问题了,第四次挥手后进行第四次挥手的一方会进入 TIME_WAIT 状态,要至少等待 2MSL 才关闭连接。
这是为了避免另一端没有收到自己的 ACK 又进行了 FIN 的重发,如果自己直接就把连接关了,那么就收不到这个 FIN 数据报了。这样一来,另一端就会长时间处在 LAST_ACK的状态。
虽然 TIME_WAIT 这个状态是出于好意,但有些时候还是为造成一些问题,特别是在 Web 服务器这种需要主动关闭连接的服务端。
2MSL 的时间长度默认情况下并不短,通常情况下可能有 30~300 秒,这意味着在这个时间段类相应的 端口 资源是一直被占据的,这对相当依赖有限的端口资源的服务器来说是难以接受的。
因此,可以考虑通过将 2MSL 调低来解决这样问题。
结语
说起来,学习计算机网络基础的时候,并没有怎么学习关于三次握手和四次挥手的内容,基本上都是简单的了解了一下就完事了。
直到面试遇到了这个问题 @_@
然后才发现,这里面的弯弯道道也还不少,而且,似乎离我们并不是那么远,也许,实际操作中的一些问题就是由这两个过程导致的。
所以说,这两个过程能称为面试问题中的常客也不是没有道理的,是真的很重要。
注:三次握手和四次挥手中还有一个比较重要的内容是状态的转换,这里基本上没有提及这方面的内容,有需要或有兴趣的可以查阅相关的资料。