三次握手的第三次握手發送ACK能攜帶數據嗎?如何攜帶?怎樣體現的呢?
如題,對於三次握手的疑問
如果我對同學們說,想透徹理解通信的本質,首先要追本溯源學習電話原理,你們會覺得我在說笑嗎?
人類先發明了電話,當電話原理成熟了,上世紀中後葉又出現了TCP/IP,TCP協議幾乎就是模仿電話原理的,為了更好學習TCP,我們要學習電話的基本原理。
三次握手的過程
第一次上海的老王給北京的老張打電話,撥號碼010-68886xx8
老王電話機與電信局之間的電話線,其實有兩個信道:信令信道 + 語音信道,
當老王拿起電話,撥010-68886xx8,這個號碼通過信令信道傳到了電信局,同時將語音信道(DS0)保留,為了稍後的通信做語音信道預留。
電信局根據這個號碼做路由查找,找到其上一級的交換機,通過信令信道將010-68886xx88轉發給上一級交換機,同時和上一級協商好,預留一個DS0語音信道,為了語音傳輸。
這樣一級級轉接,最終號碼轉接到北京老張的電話機,振鈴,北京電信局與老張電話機之間預留一個DS0語音信道,為了語音傳輸。
第二次
老張拿起電話的那一刻,一個「Connected」信令順著來時的信令信道(一跳、一跳)傳輸到老王的電話機。第三次
老王電話機通常還會回復一個「ACK」給對方,以示接到對方的「Connected」。語音傳輸
當老張拿起電話的那一刻,端到端的語音信道已經預留好了,一般為DS0= 64Kbps,這條端到端信道其實是由多條 hop-2-hop信道串聯而成的。
此時雙方可以自由說話,語音數據會從保留的語音信道流淌到對方。
從以上的描述來看,信令數據、語音數據是在自己獨立的信道里傳輸,大家井水不犯河水,互不干涉。
TCP
TCP模仿電話原理,也有自己的信令數據、應用層數據,那哪些是信令數據呢?SYNACKRSTPSHURGFIN
依靠這六個信令狀態位,與對方
1)建立連接SYN2)重置連接RST3)拆除連接FIN那什麼是應用層數據呢?就是TCP的服務對象,比如Http。
TCP也想使用電話里的雙信道,但TCP所依賴的IP網路沒有信道的概念,完全是一個共享網路的模式。
TCP沒有雙信道使用,退而求其次,只要信令數據、應用數據放在獨立的IP包傳輸到對方就好,這就是大家最熟悉的TCP工作模式:
1)三次握手建立連接
2)數據傳輸3)四次握手拆除連接
三次握手最後一個消息是客戶端發過來的ACK,如果讓應用層數據與這個信令數據合二為一,可以減少發送的IP包的數目,還可以提高效率,何樂不為呢?
TCP協議的制定者,為了提高效率,減少IP包的數目,最大可能地將信令數據、應用數據合二為一,各位同學通過抓包,可以看到一個TCP連接,除了第一個SYN包,每個TCP報文都有ACK信令,這就是合二為一的結果!
++++++++++++
如果同學們對計算機網路充滿著好奇,想徹底征服她,來參加我的live,傳授你獨家秘笈,姿勢全解鎖…Live門票入口:https://www.zhihu.com/lives/897123723914649600可以攜帶,親測有效。Windows上調用ConnectEx來建立連接並發數據。此時第三次握手會是一個普通的數據包,加上TCP頭裡ACK標誌等信息。
Add client-side API to support Windows ConnectEx optimizations and TCP Fast Open · Issue #268 · carllerche/mio
- In TCP Fast Open, the initial data to send is sent in the same packet as the initial SYN, eliminating one round-trip and thus greatly reducing latency. In Linux, this is done by using sendto (usually used for datagrams) instead of connect and send, as explained in this article: https://lwn.net/Articles/508865/.
- Windows"s ConnectEx supports a mode where the kernel will, when it receives the initial SYN/ACK in the TCP handshake from the server, immediately sends a buffer of data that was supplied in the ConnectExcall. This doesn"t reduce any network-level latency, but it does eliminate a context switch between the kernel and userspace. See the lpSendBuffer and dwSendDataLength arguments in the documentation:https://msdn.microsoft.com/en-us/library/windows/desktop/ms737606(v=vs.85).aspx.
TCP客戶端和伺服器之間,建立TCP連接要經過三次報文傳輸。
詳細的過程如下圖所示。
http://d3ojx0qwvsjea2.cloudfront.net/wp-content/uploads/2016/12/24160105/Three-way-Handshake-ex2.png
連接的主動發起者是客戶端,連接的接收方是伺服器。
第三次握手,是客戶端為了告訴伺服器,我已經收到了你發送的SYNC + ACK報文,此時這個報文只帶ACK標誌,SYNC標誌沒有。
客戶端發送這個報文之後,就進入established狀態了。伺服器收到這個報文之後,也進入established狀態。
TCP標準規定,第三次握手的報文,可以攜帶數據。因為此時客戶端已經處於established狀態了呀。
假設第三次握手的報文的seq是x+1,
如果有攜帶數據,下次客戶端發送的報文,seq=伺服器發回的ACK號。
如果沒有攜帶數據,那麼第三次握手的報文不消耗seq。下次客戶端發送的報文,seq序列號還是和第三次握手的報文的seq一樣,為x+1。這是因為,seq和報文中的數據在整條數據流流中的位置是一一對應的。如果報文沒有攜帶數據,那麼seq當然也不會更新。
第三次ACK攜帶data的叫piggyback ACK,以前的三哥教授好像教過
請搜索TCP-fastopen技術,新的Linux內核有的。
我當年做考研題的時候有的題目就說到這個 當時還蠻奇怪
可以攜帶,必需內核支持
RFC 793
握手時發送的也是標準的TCP包,只是標誌位的區別,當然可以和普通的TCP包一樣攜帶數據。另外TCP最後一次發送數據時還可以把FIN 標誌位置為1,這樣斷開連接時又省了一次。
已經實現了,叫tcp fastopen
你用wireshark抓個http請求看看,會看到這個在第三次握手時就發出去了。
推薦閱讀:
※IT公司聘用應屆生的標準是什麼?即,看中應屆生的什麼?
※為什麼一些政府網站上顯示今年是 19113 年?
※明明是軟體開發的,但別人當你是修電腦的?
※Facebook 在不斷分拆獨立業務,豆瓣卻在聚合業務,到底誰是正確的?