成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手動發包只握手兩次,我發現了TCP的秘密

網絡 通信技術
如果因為各種原因,服務端并未收到客戶端發來的第三次握手包,那客戶端后續發送的數據,服務端如何處理?

 [[399328]]

星球提問

TCP三次握手這個話題,沒有一萬,也有九千篇文章寫過了。

今天寫這篇文章,是因為有球友在我的知識星球里提了這么一個問題:

總結一下三個小問題:

客戶端發送完第三次握手后,是不是不管服務器有沒有收到,直接就發送數據?

TCP的第三次握手能不能攜帶數據?

如果因為各種原因,服務端并未收到客戶端發來的第三次握手包,那客戶端后續發送的數據,服務端如何處理?

我的回答

以下是我的回答:

首先來回答這位球友最開始的問題:客戶端發送完第三個握手后,是不是不管服務器有沒有收到,直接就發送數據?

你可以從理論上來猜測一下,如果上面這個問題的答案是否定的話,也就是說客戶端還得要確認服務器收到自己的第三次握手包以后才能發送數據。那怎么確認呢?是不是服務端還得回復自己一下:我收到了你的第三次握手包了,你可以發送數據了。

但如果這樣一來,那是不是就變成了四次握手,而不是三次握手了呢?

所以反過來想,這個問題的答案就是肯定的,即:客戶端發送完第三次握手包后,不再需要服務端的確認,立即可以發送數據。

下面是《TCP/IP協議詳解》(卷1)中的連接建立示意圖,你可以看到客戶端這一側,發送完第三次握手包以后,狀態就別變成了ESTABLISH狀態了,并未等待服務器確認,就開始在傳輸數據了。

光理論不夠,我們再來抓包看一下,下面是我用抓包軟件抓了一個TCP連接建立的握手時序圖,同樣你可以看到,在第三次握手包發送后,左側的客戶端立即就發出了正式的數據傳輸:一個HTTP請求包。

所以這個問題的答案就清楚了。

接下來看第二個問題:客戶端在發送第三次握手包的時候是不是會攜帶數據一起傳輸過去?

其實從上面的2個圖中你可以看出,TCP三次握手并未攜帶有效的應用層數據,數據的傳輸是在握手完成以后才開始的。但是如果我們非得問一句:客戶端在發送第三次握手數據包的時候,到底能不能順帶攜帶一些數據過去呢?

關于這一問題,最權威的答案還是得看RFC標準文檔,關于TCP標準協議的規范,是記錄在編號793的RFC793一文中,鏈接如下:

https://www.rfc-editor.org/rfc/rfc793.html

文檔有點長,而且是英文版,看起來可能有些吃力。

在事件處理這一節里面,會找到下面這段文字:

大意是說:如果我們的同步包SYN已經得到了確認,就把連接狀態改為ESTABLISHED,然后發送的第三次握手包中可能會包含數據(如果已經有數據在排隊等待傳輸的話)

這就說的很清楚了:TCP標準協議規范中,第三次握手包是允許傳輸數據的!

最后一個問題:如果因為各種原因,服務端并未收到客戶端發來的第三次握手包,那客戶端后續發送的數據,服務端如何處理?

這里先賣個關子,接著往下看。

接下來才是這篇文章的精華部分:

實驗論證

TCP建立連接的三次握手,是操作系統內核協議棧自動完成的,作為底層服務,這個過程對應用程序是透明的,我們開發應用程序的時候,只需要使用應用層編程接口就行了,比如套接字接口。

所以,大部分人對TCP三次握手的概念還是建立在書本上,博客里,公眾號文章里,今天,我們自己來發送TCP數據包來實現三次握手!

自己發包,來驗證我們上面的結論!

使用的工具,是之前一篇文章中提到的神器:scapy。

為了方便查看數據,我找了一個沒有HTTPS的網站,通過ping它的域名,拿到了IP地址,向其進行握手并發送GET請求包。

  1. from scapy.all import * 
  2. def tcp_test(ip, port, data): 
  3.  
  4.     # 第一次握手,發送SYN包 
  5.     # 請求端口和初始序列號隨機生成 
  6.     # 使用sr1發送而不用send發送,因為sr1會接收返回的內容 
  7.     ans = sr1(IP(dst=ip) / TCP(dport=port, sport=RandShort(), seq=RandInt(), flags='S'), verbose=False
  8.  
  9.     # 假定此刻對方已經發來了第二次握手包:ACK+SYN 
  10.  
  11.     # 對方回復的目標端口,就是我方使用的請求端口(上面隨機生成的那個) 
  12.     sport = ans[TCP].dport 
  13.     s_seq = ans[TCP].ack 
  14.     d_seq = ans[TCP].seq + 1 
  15.  
  16.     # 第三次握手,發送ACK確認包 
  17.     send(IP(dst=ip) / TCP(dport=port, sport=sport, ack=d_seq, seq=s_seq, flags='A'), verbose=False
  18.  
  19.     # 發起GET請求 
  20.     send(IP(dst=ip)/TCP(dport=port, sport=sport, seq=s_seq, ack=d_seq, flags=24)/data, verbose=False
  21.    
  22.    
  23. if __name__ == '__main__'
  24.     data = 'GET / HTTP/1.1\n' 
  25.     data += 'Host: www.chengtu.com\n' 
  26.     data += 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36\n' 
  27.     data += 'Accept: text/html' 
  28.     data += '\r\n\r\n' 
  29.  
  30.     tcp_test("150.138.151.65", 80, data) 

執行上面這段代碼,來抓包看一下:

可以看到,成功的完成了三次握手動作,服務器還返回了數據,證明手動編程來握手是可行的。

下面論證星球中,球友提出的問題:第三個握手包里面能不能攜帶數據呢?

我們來試一下就知道了:

  1. from scapy.all import * 
  2. def tcp_test_2(ip, port, data): 
  3.  
  4.     # 第一次握手,發送SYN包 
  5.     # 請求端口和初始序列號隨機生成 
  6.     # 使用sr1發送而不用send發送,因為sr1會接收返回的內容 
  7.     ans = sr1(IP(dst=ip) / TCP(dport=port, sport=RandShort(), seq=RandInt(), flags='S'), verbose=False
  8.  
  9.     # 假定此刻對方已經發來了第二次握手包:ACK+SYN 
  10.  
  11.     # 對方回復的目標端口,就是我方使用的請求端口(上面隨機生成的那個) 
  12.     sport = ans[TCP].dport 
  13.     s_seq = ans[TCP].ack 
  14.     d_seq = ans[TCP].seq + 1 
  15.  
  16.     # 第三次握手,發送ACK確認包,順帶把數據一起帶上 
  17.     send(IP(dst=ip) / TCP(dport=port, sport=sport, ack=d_seq, seq=s_seq, flags='A')/data, verbose=False
  18.  
  19.  
  20. if __name__ == '__main__'
  21.  
  22.     data = 'GET / HTTP/1.1\n' 
  23.     data += 'Host: www.chengtu.com\n' 
  24.     data += 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36\n' 
  25.     data += 'Accept: text/html' 
  26.     data += '\r\n\r\n' 
  27.  
  28.     tcp_test_2("150.138.151.65", 80, data) 

看到了吧,在第三次握手中,我的GET請求就帶過去了,TCP協議仍然能夠正常工作!

這是Linux的情況,我又找了我們大學的網站試了一下,因為學校網站沒用HTTPS(就很離譜),而且是ASP.NET技術棧做的(別問我怎么知道的),服務器是Windows,依然可以正常工作,說明Windows的協議棧也支持這種操作。

接下來驗證另一個問題:如果第三次握手包服務器沒有收到,就直接發送數據,會發生什么?

怎么驗證,很簡單,直接把發送第三次握手的那一行注釋掉,不發送第三次握手,直接發送GET請求就行了:

  1. from scapy.all import * 
  2. def tcp_test(ip, port, data): 
  3.  
  4.     # 第一次握手,發送SYN包 
  5.     # 請求端口和初始序列號隨機生成 
  6.     # 使用sr1發送而不用send發送,因為sr1會接收返回的內容 
  7.     ans = sr1(IP(dst=ip) / TCP(dport=port, sport=RandShort(), seq=RandInt(), flags='S'), verbose=False
  8.  
  9.     # 假定此刻對方已經發來了第二次握手包:ACK+SYN 
  10.  
  11.     # 對方回復的目標端口,就是我方使用的請求端口(上面隨機生成的那個) 
  12.     sport = ans[TCP].dport 
  13.     s_seq = ans[TCP].ack 
  14.     d_seq = ans[TCP].seq + 1 
  15.  
  16.     # 第三次握手,發送ACK確認包 
  17.     # send(IP(dst=ip) / TCP(dport=port, sport=sport, ack=d_seq, seq=s_seq, flags='A'), verbose=False
  18.  
  19.     # 發起GET請求 
  20.     send(IP(dst=ip)/TCP(dport=port, sport=sport, seq=s_seq, ack=d_seq, flags='A')/data, verbose=False
  21.    
  22.    
  23. if __name__ == '__main__'
  24.     data = 'GET / HTTP/1.1\n' 
  25.     data += 'Host: www.chengtu.com\n' 
  26.     data += 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36\n' 
  27.     data += 'Accept: text/html' 
  28.     data += '\r\n\r\n' 
  29.  
  30.     tcp_test("150.138.151.65", 80, data) 

結果發現依然能正常工作!分析了一下,發現這種方式其實和上面那種情況是等價的:直接在第三次握手包中帶了數據。

這里雖然把第三次握手那一行注釋了,但直接發送的那個GET請求包中,ACK標記是置位了的,所以服務端就把這個GET包當成了第三次握手了。

所以結論就是:如果第三次握手包服務器沒有收到,就直接發送數據,服務器將這個攜帶應用數據的包當做第三次握手(前提是這一個包中攜帶有ACK標記)。

除了我上面的回答外,這位球友又評論補充了一個問題:

其實看到這里,這個問題的答案想必已經心中有數了,但咱們還是來實驗模擬一下:先發送帶數據的請求包,然后再發送第三次握手包,看看會發生什么?

從圖中可以看到,直接發送的那個帶數據的請求包,被當做了第三次握手包,而后面再發送的那個名義上的第三次握手包,也就是圖中黑色的那一行,被當作了重復發送的無效包,被忽略掉了,對通信沒有造成影響。

以上就是我對這位球友問題的全部解答。

本文轉載自微信公眾號「編程技術宇宙」,可以通過以下二維碼關注。轉載本文請聯系編程技術宇宙公眾號。

 

責任編輯:武曉燕 來源: 編程技術宇宙
相關推薦

2021-04-30 13:32:17

TCP三次握手網絡協議

2024-10-16 08:38:37

TCP編號信息

2019-05-14 10:09:06

TCP連接握手

2024-05-20 08:25:55

2022-07-05 22:18:08

TCP網絡

2021-04-26 05:41:32

百度網盤秒傳

2021-07-26 08:08:56

TCPIP網絡協議

2020-08-04 08:48:34

數據彈屏技術

2020-04-01 08:40:44

Vue.jsweb開發

2024-06-03 11:43:55

2022-10-10 07:34:36

TCP三次握手區塊鏈

2020-03-10 10:43:21

機器學習人工智能計算機

2019-09-25 09:00:56

iPhone 11拆解蘋果

2020-05-18 08:42:23

CSS背景圖像前端開發

2019-05-28 10:45:07

TCP3次握手數據傳輸

2021-10-29 11:45:26

Python代碼Python 3.

2025-06-04 08:10:59

2021-07-10 07:40:27

Excel數據分析大數據

2021-12-02 09:20:33

TCPLinux三次握手

2025-05-19 10:04:48

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美亚洲视频 | 成人免费在线网 | 亚洲国内精品 | 日韩欧美在线视频 | 国产一区二区三区四区在线观看 | 日本不卡一区二区三区在线观看 | 中文字幕亚洲区一区二 | 在线观看黄色电影 | 日韩中文在线视频 | 一区二区三区国产好的精 | 欧美日韩亚洲一区 | 999久久久国产精品 欧美成人h版在线观看 | 日本免费视频在线观看 | 久久99精品久久 | 久久久久国产一区二区三区四区 | 国外成人免费视频 | 毛片免费在线 | 国产欧美精品区一区二区三区 | 中文视频在线 | 中国av在线免费观看 | 久久久久久久国产 | 91麻豆产精品久久久久久夏晴子 | 国产精品高清一区二区 | 五月槐花香 | 欧美精品第一页 | 夜夜骑首页 | 国产精品18久久久 | 99爱在线观看 | 亚洲色图综合 | 婷婷精品 | 欧美精品久久 | av中文在线 | 毛片视频网站 | 一级片网站视频 | 四虎影院在线观看免费视频 | 中文字幕国产 | 羞羞网站免费观看 | 91精品国产色综合久久 | 国产av毛片 | 自拍视频网 | 亚洲一区二区三区四区五区中文 |