socket 由淺入深系列 原理(一)

2021-09-08 12:48:18 字數 2937 閱讀 5640

來自:網路整理

個人覺得寫乙個網路應用程式沒有是一件非常easy的事。其實,我們剛開始的時候總覺得的原則:

建立------》連線套接字-------》接受乙個連線----》傳送資料

而真正複雜編寫乙個網路應用程式的規模從乙個連線到成千上萬的連線!

那麼本系列將對sockt由淺入深的介紹. 

msdn

詳細作用參考:socket 由淺入深 系列函式(二)

msdn樣例

handle    hiocp;

hiocp = createiocompletionport(

invalid_handle_value,

null,

(ulong_ptr)0,

0);if (hiocp == null)

要寫網路程式就必須用socket,這是程式猿都知道的。

並且,面試的時候,我們也會問對方會不會socket程式設計?一般來說,非常多人都會說。socket程式設計基本就是listen,accept以及send,write等幾個主要的操作。是的,就跟常見的檔案操作一樣,僅僅要寫過就一定知道。

對於網路程式設計,我們也言必稱tcp/ip,似乎其他網路協議已經不存在了。

對於tcp/ip。我們還知道tcp和udp,前者能夠保證資料的正確和可靠性,後者則同意資料丟失。最後,我們還知道,在建立連線前,必須知道對方的ip位址和port號。

除此,普通的程式猿就不會知道太多了。非常多時候這些知識已經夠用了。最多,寫服務程式的時候,會使用多執行緒來處理併發訪問。

我們還知道例如以下幾個事實:

1。乙個指定的port號不能被多個程式共用。比方,假設iis占用了80port。那麼apache就不能也用80port了。

2。非常多防火牆僅僅同意特定目標port的資料報通過。

3。服務程式在listen某個port並accept某個連線請求後,會生成乙個新的socket來對該請求進行處理。

於是,乙個困惑了我非常久的問題就產生了。

假設乙個socket建立後並與80port繫結後,是否就意味著該socket占用了80port呢?假設是這種,那麼當其accept乙個請求後。生成的新的socket究竟使用的是什麼port呢(我一直以為系統會預設給其分配乙個空暇的port號)?假設是乙個空暇的port,那一定不是80port了,於是以後的tcp資料報的目標port就不是80了--防火牆一定會組織其通過的。實際上,我們能夠看到,防火牆並沒有阻止這種連線。並且這是最常見的連線請求和處理方式。

我的不解就是,為什麼防火牆沒有阻止這種連線?它是怎樣判定那條連線是由於connet80port而生成的?是不是tcp資料報裡有什麼特別的標誌?或者防火牆記住了什麼東西?

後來,我又細緻研讀了tcp/ip的協議棧的原理。對非常多概念有了更深刻的認識。比方,在tcp和udp同屬於傳輸層,共同架設在ip層(網路層)之上。而ip層主要負責的是在節點之間(end to end)的資料報傳送,這裡的節點是一台網路裝置。比方計算機。由於ip層僅僅負責把資料送到節點。而不能區分上面的不同應用。所以tcp和udp協議在其基礎上增加了port的資訊。port於是標識的是乙個節點上的乙個應用。除了增加port資訊,upd協議基本就沒有對ip層的資料進行不論什麼的處理了。而tcp協議還增加了更加複雜的傳輸控制。比方滑動的資料傳送窗體(slice window),以及接收確認和重發機制,以達到資料的可靠傳送。無論應用層看到的是如何乙個穩定的tcp資料流,以下傳送的都是乙個個的ip資料報。須要由tcp協議來進行資料重組。

所以。我有理由懷疑。防火牆並沒有足夠的資訊推斷tcp資料報的很多其它資訊,除了ip位址和port號。並且。我們也看到。所謂的port。是為了區分不同的應用的,以在不同的ip包來到的時候可以正確**。

tcp/ip僅僅是乙個協議棧,就像作業系統的執行機制一樣,必需要詳細實現,同一時候還要提供對外的操作介面。

就像作業系統會提供標準的程式設計介面。比方win32程式設計介面一樣,tcp/ip也必須對外提供程式設計介面,這就是socket程式設計介面--原來是這麼回事啊!

在socket程式設計介面裡,設計者提出了乙個非常重要的概念,那就是socket。這個socket跟檔案控制代碼非常相似,實際上在bsd系統裡就是跟檔案控制代碼一樣存放在一樣的程序控制代碼表裡。

這個socket事實上是乙個序號,表示其在控制代碼表中的位置。這一點,我們已經見過非常多了。比方檔案控制代碼,窗體控制代碼等等。

這些控制代碼,事實上是代表了系統中的某些特定的物件,用於在各種函式中作為引數傳入。以對特定的物件進行操作--這事實上是c語言的問題,在c++語言裡,這個控制代碼事實上就是this指標,實際就是物件指標啦。

如今我們知道,socket跟tcp/ip並沒有必定的聯絡。socket程式設計介面在設計的時候,就希望也能適應其它的網路協議。

所以。socket的出現僅僅是能夠更方便的使用tcp/ip協議棧而已。其對tcp/ip進行了抽象,形成了幾個最主要的函式介面。

比方create,listen,accept,connect,read和write等等。

如今我們明確。假設乙個程式建立了乙個socket,並讓其監聽80port,事實上是向tcp/ip協議棧宣告了其對80port的占有。以後,全部目標是80port的tcp資料報都會**給該程式(這裡的程式,由於使用的是socket程式設計介面,所以首先由socket層來處理)。

所謂accept函式,事實上抽象的是tcp的連線建立過程。accept函式返回的新socket事實上指代的是本次建立的連線。而乙個連線是包括兩部分資訊的。乙個是源ip和源port,還有乙個是宿ip和宿port。所以。accept能夠產生多個不同的socket。而這些socket裡包括的宿ip和宿port是不變的。變化的僅僅是源ip和源port。

這種話,這些socket宿port就能夠都是80,而socket層還是能依據源/宿對來準確地分辨出ip包和socket的歸屬關係。從而完畢對tcp/ip協議的操作封裝!

而同一時候,放火牆的對ip包的處理規則也是清晰明了。不存在前面設想的種種複雜的情形。

明確socket僅僅是對tcp/ip協議棧操作的抽象,而不是簡單的對映關係,這非常重要

socket系列(一) socket實現推送

設想 用socket實現伺服器與客戶端的tcp長連線,保持outputstream inputstream連線,通過輸入輸出流實現資訊實時推送 public classtestpush socket.shutdownoutput serviceos.close socket.close suppre...

由淺入深解析HashMap系列二 擴容

由淺入深解析hashmap系列一 hashmap簡單實現 增 刪 查。前面簡單的實現了hashmap的增刪查功能,這一章節主要是介紹擴容 不考慮衝突 當陣列元素達到一定閾值時,需要擴容,擴容之後,需要對原來的陣列中的元素進行再次hash。在開始之前先介紹幾個概念 初始容量 default initi...

socket程式設計原理

if newsock accept mysock.daemonsock,addr,len 1 return 1 accept error.set this socket as a non blocking socket.ioctl newsock,fionbio,flag fd set newsoc...