為啥"三次握手"確認序號要加1?
其實加1只是表象,加長度才是本質。但是,為啥要加長度?
了解TCP三次握手的人都知道,其ACK確認報文會有一個確認序號ack_seq,這個序號的值則為SYN連接報文的序號加1。
圖片
即假如客戶端向服務器發送連接請求,它會先發一個SYN報文。假設這個報文序號為x的話,收到請求的服務器會用ACK報文應答,并將ACK報文的確認序號賦值為x+1。意思是“收到x號報文了”。
這里難免讓人疑惑,既然是表達“收到x號報文”,ACK的確認序號不應該是賦值為x嗎?為啥是x+1,加1的作用是什么?
正如開頭所說,加1只是表象,加長度才是本質。這里1表達的是SYN連接報文的數據長度。這個長度的單位是字節,加1就表示收到了數據長度為1字節的報文,加m則表示收到數據長度為m字節的報文。
也許有人會追問,SYN作為連接請求報文,哪有什么數據,其數據長度不應該是零嗎?為啥要加1?
圖片
這是因為,雖然SYN報文的數據部分確實為空,但是它卻實實在在占據了一個報文序號x,而一個報文序號是要對應一個字節的,這時即使它實際沒有占用任何一個字節放數據,那一個字節也被消耗了。
所以,“ack_seq=x+1”更準確的翻譯應該是“收到了起始序號為x長度為1的報文數據”。這種ack_seq=seq+length的方式其優勢在于,配合序號的連續性,當需要確認的數據不止一個字節時,仍舊可以只用一個ACK報文進行應答。
不知是否有人疑惑,前文所述的SYN連接報文的編號x,一會說它是報文序號,一會又說一個報文序號對應了一個字節,那到底序號x是報文編號還是字節編號呢?
答案是,它既是報文編號也是字節編號,也就是一個編號兩個身份。但這只是一個報文的數據起始字節編號才有的特權。這就像各種編程語言中的數組,其內部第一個數組項的地址,既是當前數組項的地址,也代表整個數組的地址。