計算機網路再次整理————socket[一]

敖毛毛發表於2022-02-01

前言

以前也整理過吧,寫了幾篇之後,感覺沒啥整理的必要了然後就放棄了,最近又想整理一下。

正文

這篇對應的是:https://www.cnblogs.com/aoximin/p/12235333.html,可以說是這篇的重寫吧。

首先介紹一下什麼是socket的,如果搞學術的不知道,他們可能要求的比較嚴,但是對於碼農來說,socket可以說是向作業系統申請網路資源。

這個資源可以讓我們傳送資料和接收資料,這樣就可以了。就像我們上面那篇文章寫的,作業系統就是服務端,我們寫的都是客戶端,我們做的就是和服務端打交道。

如果真的想了解這個socket,那麼應該去了解作業系統,如果是瞭解網路,初學的話,那大可不必。

就跟前後端一樣,後端告訴你一個token,然後前端總糾結這個token是啥,我覺得大可不必,你傳給我服務端我就給你過唄。

有時候我們要放大我們的思維,有時候我們要縮小自己的思維。 如果從客戶端的角度去考慮socket,就跟前端去考慮token 是一樣的,又痛苦又無趣。當你花點時間去了解後端,這個問題自然就解了。天生萬物,道法自然,一切都是機緣,不要強求。

現在瞭解了,socket 就是資源。

有了作業系統給我們的socket 的資源後,我們就可以做一些其他事情了。

比如我們告訴作業系統,我們要佔用127.0.0.1 的 8888 埠。

那麼我們可以使用bind 來告訴作業系統。以前我有個誤區,就是一隻理解bind為繫結的意思,後面我理解的是應該是申請的意思。

要申請這個127.0.0.1 8888這個資源。所以如果有一個程式申請了這個資源,其他程式就不能申請了。

通常每個套接字地址(協議/網路地址/埠)只允許使用一次。

但是我們知道,這個返回的socket 是個描述符,假如我們的這個描述符給其他程式使用,那麼是否能共享這個資源呢?

如果這個成立,那麼一切都回到了資源這個話題,而不能再說什麼佔用的情況,什麼程式之間不能公用一個網路的情況。

這個後面提及,不然一直往外推,就太大了。

現在回到了socket這個話題了。bind 申請了這個套接字佔用了某個網路資源了。

那麼為何我們要進行listen呢? bind 是資源佔用,現在作業系統記錄了這個網路資源屬於某個socket了,其他socket就不能佔用了。

但是有個問題,就是佔用相當於作業系統內部的操作。作業系統可沒有說要處理收到的訊息啊。

作業系統處理訊息相當於流水線,訊息過來了,但是我們的指揮部還沒要處理到127.0.0.1 8888地址的訊息啊。

那麼listen 就是告訴流水線,處理一下127.0.0.1 8888的訊息,有到這個的地址的包裹存一下。

那麼現在流水線上的資源會被存起來了,但是這個是存到了作業系統了,還沒到我們的程式。

這個時候客戶端程式已經可以傳送連線和訊息到我們作為伺服器申請了127.0.0.1 8888的這臺機器了。

前面說了包裹還在我們作業系統那裡,那麼就得問一下(accept),有沒有人發包裹給我。

然後作業系統如果有的話,就會告訴隔壁家的大爺發了點東西給你。

這個時候你就會拿到客戶端會話,然後給作業系統說接受一下(receive)包裹吧。

這個時候我們思考一下問題,那就是tcp是雙向通訊的,這個時候我要收大爺包裹的時候,突然大爺掉線了,tcp斷了。

請問這個時候作業系統還會給我包裹嗎?

遠端主機強迫關閉了一個現有的連線。

這時候你就會收到上面這個,這個時候作業系統就不給你快取的包裹了,至於作業系統啥時候清空快取這是作業系統乾的事情。

這個時候再思考另外一個問題,如果是大爺發了包裹給我,然後又斷開了。這個時候我們才開始進行accept,作業系統還會告訴我們大爺給過包裹嗎?

是會的,來電顯示還是會給的。

這大概就是基本的tcp 通訊了。

自己寫的測試程式碼 .net 6:

service:

// See https://aka.ms/new-console-template for more information

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();
var clientSocket = socket.Accept();
var receiveMessage = new Byte[1000];
clientSocket.Receive(receiveMessage);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(receiveMessage));
Console.ReadLine();

client:

// See https://aka.ms/new-console-template for more information

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.ReadLine();

以上只是個人理解,可能存在錯誤,望請指出。

相關文章