### Socket三次握手及四次揮手

三次握手過程:
* 第一次握手:建立連接。客戶端發送連接請求報文段,將SYN位置為1,Sequence Number為x;然后,客戶端進入SYN\_SEND狀態,等待服務器的確認;
* 第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgment Number為x+1\(Sequence Number+1\);同時,自己自己還要發送SYN請求信息,將SYN位置為1,Sequence Number為y;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一并發送給客戶端,此時服務器進入SYN\_RECV狀態;
* 第三次握手:客戶端收到服務器的SYN+ACK報文段。然后將Acknowledgment Number設置為y+1,向服務器發送ACK報文段,這個報文段發送完畢以后,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
完成了三次握手,客戶端和服務器端就可以開始傳送數據。以上就是TCP三次握手的總體介紹。
_**注意:現代的TCP棧都允許客戶端在這個確認分組中發送數據**_
當客戶端和服務器通過三次握手建立了TCP連接以后,當數據傳送完畢,肯定是要斷開TCP連接的啊。那對于TCP的斷開連接,這里就有了神秘的“四次分手”。
* 第一次分手:主機1(可以使客戶端,也可以是服務器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN\_WAIT\_1狀態;這表示主機1沒有數據要發送給主機2了;
* 第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN\_WAIT\_2狀態;主機2告訴主機1,我“同意”你的關閉請求;
* 第三次分手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST\_ACK狀態;
* 第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然后主機1進入TIME\_WAIT狀態;主機2收到主機1的ACK報文段以后,就關閉連接;此時,主機1等待2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。
### tcp標志位
* SYN\(synchronous建立聯機\)
* ACK\(acknowledgement 確認\)
* PSH\(push傳送\)
* FIN\(finish結束\)
* RST\(reset重置\)
* URG\(urgent緊急\)
### 為什么一定要進行三次握手來保證連接是雙工?
為什么需要三次握手,兩次不行嗎?
1. 第一次握手:客戶端發送網絡包,服務端收到了。
這樣服務端就能得出結論:客戶端的發送能力、服務端的接收能力是正常的。
2. 第二次握手:服務端發包,客戶端收到了。
這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。不過此時服務器并不能確認客戶端的接收能力是否正常。
3. 第三次握手:客戶端發包,服務端收到了;
這樣服務端就能得出結論:客戶端的接收、發送能力正常,服務器自己的發送、接收能力也正常
需要三次握手才能確認雙方的接收與發送能力是否正常
> 這個問題的本質是, 信道不可靠, 但是通信雙發需要就某個問題達成一致. 而要解決這個問題, 無論你在消息中包含什么信息, 三次通信是理論上的最小值. 所以三次握手不是TCP本身的要求, 而是為了滿足"在不可靠信道上可靠地傳輸信息"這一需求所導致的. 請注意這里的本質需求,信道不可靠, 數據傳輸要可靠
### 第三次握手是為了防止異常情況下服務端一直等待而浪費時間
如客戶端發出連接請求,但因連接請求報文丟失而未收到確認,于是客戶端再重傳一次連接請求。后來收到了確認,建立了連接。數據傳輸完畢后,就釋放了連接,客戶端共發出了兩個連接請求報文段,其中第一個丟失,第二個到達了服務端,但是第一個丟失的報文段只是在某些網絡結點長時間滯留了,延誤到連接釋放以后的某個時間才到達服務端,此時服務端誤認為客戶端又發出一次新的連接請求,于是就向客戶端發出確認報文段,同意建立連接,不采用三次握手,只要服務端發出確認,就建立新的連接了,此時客戶端忽略服務端發來的確認,也不發送數據,則服務端一致等待客戶端發送數據,浪費資源
### 三次握手過程中可以攜帶數據嗎?
第三次握手的時候,可以攜帶數據,第一次、第二次握手不可以攜帶數據;
假如第一次握手可以攜帶數據的話,如果有人要惡意攻擊服務器,那他每次都在第一次握手中的 SYN 報文中放入大量的數據。因為攻擊者根本就不理服務器的接收、發送能力是否正常,然后瘋狂著重復發 SYN 報文的話,這會讓服務器花費很多時間、內存空間來接收這些報文;
對于第三次的話,此時客戶端已經處于 ESTABLISHED 狀態。對于客戶端來說,他已經建立起連接了,并且也已經知道服務器的接收、發送能力是正常的了,所以能攜帶數據也沒問題
#### 為什么要四次分手
那四次分手又是為何呢?TCP協議是一種面向連接的、可靠的、基于字節流的運輸層通信協議。TCP是全雙工模式,這就意味著,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之后彼此就會愉快的中斷這次TCP連接。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態變化。
* FIN\_WAIT\_1: 這個狀態要好好解釋一下,其實FIN\_WAIT\_1和FIN\_WAIT\_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN\_WAIT\_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN\_WAIT\_1狀態。而當對方回應ACK報文后,則進入到FIN\_WAIT\_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN\_WAIT\_1狀態一般是比較難見到的,而FIN\_WAIT\_2狀態還有時常常可以用netstat看到。(主動方)
* FIN\_WAIT\_2:上面已經詳細解釋了這種狀態,實際上FIN\_WAIT\_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你\(ACK信息\),稍后再關閉連接。(主動方)
* CLOSE\_WAIT:這種狀態的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE\_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那么你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE\_WAIT狀態下,需要完成的事情是等待你去關閉連接。(被動方)
* LAST\_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態了。(被動方)
* TIME\_WAIT: 表示收到了對方的FIN報文,并發送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME\_WAIT狀態,而無須經過FIN\_WAIT\_2狀態。(主動方)
* CLOSED: 表示連接中斷。
### 揮手為什么需要四次?
因為當服務端收到客戶端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當服務端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴客戶端,“你發的FIN報文我收到了”。只有等到我服務端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四次揮手
### 四次揮手釋放連接時,等待2MSL的意義?
為了保證客戶端發送的最后一個ACK報文段能夠到達服務器。因為這個ACK有可能丟失,從而導致處在LAST-ACK狀態的服務器收不到對FIN-ACK的確認報文。服務器會超時重傳這個FIN-ACK,接著客戶端再重傳一次確認,重新啟動時間等待計時器。最后客戶端和服務器都能正常的關閉。假設客戶端不等待2MSL,而是在發送完ACK之后直接釋放關閉,一但這個ACK丟失的話,服務器就無法正常的進入關閉連接狀態
- 概述
- 網絡時延
- 進程間通信
- URI
- URL
- URN
- NAT
- 操作系統基礎
- 內核
- 用戶空間
- 網絡協議模型
- 四層網絡協議模型
- 鏈路層
- 以太網協議
- ARP協議
- RARP協議
- MAC地址
- 網絡層
- IP協議
- ICMP協議
- 子網掩碼
- 傳輸層
- TCP協議
- TCP慢啟動
- TCP性能
- UDP協議
- SCTP協議
- 應用層
- DNS
- TCP/IP協議族
- Socket
- Socket通信模型
- socket和TCP/IP協議族
- Socket三次握手四次揮手
- OSI七層模型
- 物理層
- 數據鏈路層
- 網絡層
- 傳輸層
- 應用層
- HTTP
- 基礎
- HTTP/1.0
- HTTP/1.1
- http2.0
- HTTP報文
- WEB瀏覽器工作機制
- HTTP事務時延
- HTTP與HTTPS區別
- 持久連接
- 用戶驗證
- web結構組件
- 代理
- 正向代理
- 反向代理
- 緩存
- 網關
- 隧道-tunnel
- Agent代理
- http協議補充
- Servlet3異步請求
- ajax
- Comet
- WebSocket
- SPDY協議
- HTTP/2
- QUIC
- WebDAV
- http方法
- http連接
- 短連接&長連接
- 管線化
- 網絡會話
- cookie
- session
- token
- jwt
- cookie與session的區別
- Spring Session
- 分布式session實現方案
- 同源策略
- 跨域
- CORS
- HTTP三大安全問題
- JWT vs OAuth
- HTTPS
- SSL&TLS
- OpenSSL
- HTTPS和TLS/SSL的關系
- X509標準和PKI
- IO模型
- IO
- I/O模型
- 傳統阻塞式I/O
- 非阻塞式I/O
- IO復用
- Connection Per Thread模式
- IO多路復用模型流程
- Reactor模式
- 單Reactor單線程
- 單Reactor多線程
- 主從Reactor多線程
- Proactor模型
- Selector模型
- 信號驅動I/O
- 異步I/O
- select/poll/epoll
- select
- poll
- epoll
- select/poll/epoll適用場景
- 零拷貝原理
- 讀取文件發送網絡內存拷貝
- 零拷貝
- Netty零拷貝
- 密碼學
- 密碼學Hash算法分類
- 加密算法
- 對稱加密
- 非對稱加密
- 數字簽名
- RSA數字簽名算法
- DSA數字簽名算法
- 數字證書
- MAC算法
- web安全
- CSRF攻擊
- XSS
- cookie劫持
- SQL注入
- DDos攻擊
- 常見面試題
- 瀏覽器工作機制和原理
- XSS如何預防
- 如何防止cookie被劫持
- 附錄
- HTTP狀態碼
- 常用的網絡端口