前言
前文我們介紹了網路協議的各層,同時也介紹了一下我們在編寫程式碼時候的服務端的accept、bind、listen、connect、send做了什麼。
可以說是從巨集觀的角度,或者程式碼開發的角度來說的,在此我覺得還不夠具體。
同樣我想解釋一下為什麼我說服務端listen之後,客戶端已經可以進行tcp連線了,同樣可以傳送訊息了。
正文
首先我們的tcp連線網圖:
前提,這個時候服務端只是listen了,並沒有accept。且客戶端呼叫了connect,同時send 了hello word了。
第一個包:
客戶端發起tcp連線。
上面可以看到seq 為0,同樣有0x002 SYN 標誌。
第二個包:
這是伺服器端給客戶端的.
說明此時服務端是認可了客戶端的請求的,並且呢,開始進行了確認操作。
第三個包:
這是客戶端發出的,3次握手已經完成了,說明已經連線上了。
然後就是要確認之後listen 之後是否可以傳送訊息。
第四個包:
客戶端已經向服務端發起了訊息。
可以看到資料是:68656c6c6f2073657276696365
大家可以用utf8 16進位制進行解碼看下解密出來的是啥。
第五個包:
服務端的確認包。說明服務端確認收到了資料的。
其實這些連線和收包前文提及了,其實都是作業系統幫助我們做了。
那麼為什麼有些書本要寫,accept 之後才是連線呢?
這是因為相當我們的應用程式而言的,accept之後,我們才能知道客戶端連線過來的在服務端建立的socket是多少。
這個時候服務端才知道有客戶端進行了連線了,所以認為這個時候才連線成功了。而一些書本認為服務端也不包含作業系統,僅是我們的應用程式。
這裡我用的是wireshark 進行抓包的。
本來想把四次揮手也截圖出來的,但是後面向介紹一些更具體的東西,所以往後推一推吧,這樣也不會冗餘,同時大家交流起來更加的自然。
實驗程式碼如下:
服務端:
using System.Net;
using System.Net.Sockets;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Bind(endPoint);
socket.Listen();
Console.ReadLine();
客戶端:
using System.Net;
using System.Net.Sockets;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Connect(endPoint);
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service"));
Console.WriteLine("傳送成功");
Console.ReadLine();
結
以上只是個人的整理,如有錯誤,望請指點。