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

前言

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

正文

這篇對應的是: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();

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章