淺談網(wǎng)絡(luò)九-你真的知道Socket是什么嗎烤送?

Socket 一說起來肯定都并不陌生,大概一說出來所有人的第一反應(yīng)就是糠悯,這是個做端到端長連接通信的帮坚。一點問題沒有,很對互艾。但是如果要是有人問起试和,基于UDP的Socket和基于TCP的Socket有什么區(qū)別?一個Socket的連接都經(jīng)歷了什么纫普?監(jiān)聽Socket和真正Socket傳輸是一個Socket嗎阅悍?Socket編程都要設(shè)置啥參數(shù)?等等的一系列問題昨稼。如果這些問題你能夠做到胸有成竹节视,大概這邊文章對你也沒啥用處。如果想要了解下的可以接著往下看假栓。

建立Socket需要設(shè)置很多參數(shù)寻行?

并不是的,其實學(xué)習(xí)它并不需要記住很多亂七八糟意義的參數(shù)但指,因為Socket 編程進行的是端到端的通信寡痰,往往意識不到中間經(jīng)過多少局域網(wǎng),多少路由棋凳,拦坠,因而能夠設(shè)置的參數(shù),也只能是端到端協(xié)議之上網(wǎng)絡(luò)層和傳輸層的剩岳。

在網(wǎng)絡(luò)層贞滨,Socket 函數(shù)需要指定到底是 IPv4 還是 IPv6,分別對應(yīng)設(shè)置為 AF_INET 和 AF_INET6拍棕。另外晓铆,還要指定到底是 TCP 還是 UDP。TCP 協(xié)議是基于數(shù)據(jù)流的绰播,所以設(shè)置為 SOCK_STREAM骄噪,而 UDP 是基于數(shù)據(jù)報的,因而設(shè)置為 SOCK_DGRAM蠢箩。

監(jiān)聽Socket和真正Socket傳輸是一個Socket嗎链蕊?

上面講到了,Socket會分為是基于TCP的還是基于UDP的谬泌。

對于TCP而言滔韵,首先說明,監(jiān)聽和傳輸并不是一個Socket掌实。為什么呢陪蜻?那就要先說明下基于TCP的Socket的連接過程。

TCP 的服務(wù)端要先監(jiān)聽一個端口贱鼻,一般是先調(diào)用 bind 函數(shù)宴卖,給這個 Socket 賦予一個 IP 地址和端口。當(dāng)服務(wù)端有了 IP 和端口號忱嘹,就可以調(diào)用 listen 函數(shù)進行監(jiān)聽嘱腥。在 TCP 的狀態(tài)里面,有一個 listen 狀態(tài)拘悦,當(dāng)調(diào)用這個函數(shù)之后齿兔,服務(wù)端就進入了這個狀態(tài),這個時候客戶端就可以發(fā)起連接了础米。在內(nèi)核中分苇,為每個 Socket 維護兩個隊列。一個是已經(jīng)建立了連接的隊列屁桑,這時候連接三次握手已經(jīng)完畢医寿,處于 established 狀態(tài);一個是還沒有完全建立連接的隊列蘑斧,這個時候三次握手還沒完成靖秩,處于 syn_rcvd 的狀態(tài)须眷。接下來,服務(wù)端調(diào)用 accept 函數(shù)沟突,拿出一個已經(jīng)完成的連接進行處理花颗。如果還沒有完成,就要等著惠拭。在服務(wù)端等待的時候扩劝,客戶端可以通過 connect 函數(shù)發(fā)起連接。先在參數(shù)中指明要連接的 IP 地址和端口號职辅,然后開始發(fā)起三次握手棒呛。內(nèi)核會給客戶端分配一個臨時的端口。一旦握手成功域携,服務(wù)端的 accept 就會返回另一個 Socket簇秒。

對于 UDP 來講,過程有些不一樣秀鞭。UDP 是沒有連接的宰睡,所以不需要三次握手,也就不需要調(diào)用 listen 和 connect气筋,但是拆内,UDP 的的交互仍然需要 IP 和端口號,因而也需要 bind宠默。UDP 是沒有維護連接狀態(tài)的麸恍,因而不需要每對連接建立一組 Socket,而是只要有一個 Socket搀矫,就能夠和多個客戶端通信抹沪。也正是因為沒有連接狀態(tài),每次通信的時候瓤球,都調(diào)用 sendto 和 recvfrom融欧,都可以傳入 IP 地址和端口。

基于TCP和基于UDP的Socket連接過程是怎樣的卦羡?

圖一.連接過程

上面基本介紹了Socket的連接過程噪馏,不過需要注意的是以下幾點:

1.TCP的服務(wù)端要先監(jiān)聽一個端口,一般是先調(diào)用 bind 函數(shù)绿饵,給這個 Socket 賦予一個 IP 地址和端口欠肾。為什么需要端口呢?要知道拟赊,你寫的是一個應(yīng)用程序刺桃,當(dāng)一個網(wǎng)絡(luò)包來的時候,內(nèi)核要通過 TCP 頭里面的這個端口吸祟,來找到你這個應(yīng)用程序瑟慈,把包給你桃移。

2.基于TCP的Scoket為什么要 IP 地址呢?有時候葛碧,一臺機器會有多個網(wǎng)卡谴轮,也就會有多個 IP 地址,你可以選擇監(jiān)聽所有的網(wǎng)卡吹埠,也可以選擇監(jiān)聽一個網(wǎng)卡,這樣疮装,只有發(fā)給這個網(wǎng)卡的包缘琅,才會給你。

3.說 TCP 的 Socket 在 Linux 中就是以文件的形式存在的廓推。除此之外刷袍,還存在文件描述符。寫入和讀出樊展,也是通過文件描述符呻纹。

有限的服務(wù)器資源如何接更多的連接?

首先沒事下為什么要考慮這個問題专缠?答案很簡單雷酪,就是如何在有限的資源內(nèi)支持更多的連接。

一般來說涝婉,服務(wù)器通常固定在某個本地端口上監(jiān)聽哥力,等待客戶端的連接請求。因此墩弯,服務(wù)端端 TCP 連接四元組中只有對端 IP, 也就是客戶端的 IP 和對端的端口吩跋,也即客戶端的端口是可變的,因此渔工,最大 TCP 連接數(shù) = 客戶端 IP 數(shù)×客戶端端口數(shù)锌钮。對 IPv4,客戶端的 IP 數(shù)最多為 2 的 32 次方引矩,客戶端的端口數(shù)最多為 2 的 16 次方梁丘,也就是服務(wù)端單機最大 TCP 連接數(shù),約為 2 的 48 次方旺韭。

當(dāng)然兰吟,服務(wù)端最大并發(fā) TCP 連接數(shù)遠不能達到理論上限。首先主要是文件描述符限制茂翔,按照上面的原理混蔼,Socket 都是文件,所以首先要通過 ulimit 配置文件描述符的數(shù)目珊燎;另一個限制是內(nèi)存惭嚣,按上面的數(shù)據(jù)結(jié)構(gòu)遵湖,每個 TCP 連接都要占用一定內(nèi)存,操作系統(tǒng)是有限的晚吞。

這里我提出一個現(xiàn)在我個人覺得最好的一種方式:基于消息的IO多路復(fù)用延旧。

所謂的多路復(fù)用通俗的類比一個例子就是,一個項目組照看多個項目槽地,每個項目組都應(yīng)該有個項目進度墻迁沫,將自己組看的項目列在那里,一旦某個項目有了進展捌蚊,就派人去盯一下集畅。這個“項目進度墻”,是指一個文件描述符集合 fd_set 缅糟,由于 Socket 是文件描述符挺智,所以某個線程盯的所有的 Socket,都會被存放在里面窗宦。

如果有了改變赦颇,就會觸發(fā)事件進行通知,從而進行處理赴涵。能完成這件事情的函數(shù)叫 epoll媒怯,它在內(nèi)核中的實現(xiàn)不是通過輪詢的方式,而是通過注冊 callback 函數(shù)的方式髓窜,當(dāng)某個文件描述符發(fā)送變化的時候沪摄,就會主動通知。

圖二.監(jiān)聽示例

如圖所示纱烘,假設(shè)進程打開了 Socket m, n, x 等多個文件描述符杨拐,現(xiàn)在需要通過 epoll 來監(jiān)聽是否這些 Socket 都有事件發(fā)生。其中 epoll_create 創(chuàng)建一個 epoll 對象擂啥,也是一個文件哄陶,也對應(yīng)一個文件描述符,同樣也對應(yīng)著打開文件列表中的一項哺壶。在這項里面有一個紅黑樹屋吨,在紅黑樹里,要保存這個 epoll 要監(jiān)聽的所有 Socket山宾。

當(dāng) epoll_ctl 添加一個 Socket 的時候至扰,其實是加入這個紅黑樹,同時紅黑樹里面的節(jié)點指向一個結(jié)構(gòu)资锰,將這個結(jié)構(gòu)掛在被監(jiān)聽的 Socket 的事件列表中敢课。當(dāng)一個 Socket 來了一個事件的時候,可以從這個列表中得到 epoll 對象,并調(diào)用 call back 通知它直秆。

這種通知方式使得監(jiān)聽的 Socket 數(shù)據(jù)增加的時候濒募,效率不會大幅度降低,能夠同時監(jiān)聽的 Socket 的數(shù)目也非常的多了圾结。上限就為系統(tǒng)定義的瑰剃、進程打開的最大文件描述符個數(shù)。因而筝野,epoll 被稱為解決 C10K 問題的利器晌姚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市歇竟,隨后出現(xiàn)的幾起案子挥唠,更是在濱河造成了極大的恐慌,老刑警劉巖途蒋,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異馋记,居然都是意外死亡号坡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門梯醒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宽堆,“玉大人,你說我怎么就攤上這事茸习⌒罅ィ” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵号胚,是天一觀的道長籽慢。 經(jīng)常有香客問我,道長猫胁,這世上最難降的妖魔是什么箱亿? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮弃秆,結(jié)果婚禮上届惋,老公的妹妹穿的比我還像新娘。我一直安慰自己菠赚,他們只是感情好脑豹,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衡查,像睡著了一般瘩欺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天击碗,我揣著相機與錄音筑悴,去河邊找鬼。 笑死稍途,一個胖子當(dāng)著我的面吹牛阁吝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播械拍,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼突勇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坷虑?” 一聲冷哼從身側(cè)響起甲馋,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迄损,沒想到半個月后定躏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡芹敌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年痊远,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氏捞。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡碧聪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出液茎,到底是詐尸還是另有隱情逞姿,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布捆等,位于F島的核電站滞造,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏栋烤。R本人自食惡果不足惜断部,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望班缎。 院中可真熱鬧蝴光,春花似錦、人聲如沸达址。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沉唠。三九已至疆虚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背径簿。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工罢屈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篇亭。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓缠捌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親译蒂。 傳聞我的和親對象是個殘疾皇子曼月,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 網(wǎng)絡(luò)編程 一.楔子 你現(xiàn)在已經(jīng)學(xué)會了寫python代碼哑芹,假如你寫了兩個python文件a.py和b.py,分別去運...
    go以恒閱讀 2,024評論 0 6
  • 計算機網(wǎng)絡(luò)概述 網(wǎng)絡(luò)編程的實質(zhì)就是兩個(或多個)設(shè)備(例如計算機)之間的數(shù)據(jù)傳輸捕透。 按照計算機網(wǎng)絡(luò)的定義聪姿,通過一定...
    蛋炒飯_By閱讀 1,231評論 0 10
  • 網(wǎng)絡(luò)編程 網(wǎng)絡(luò)編程對于很多的初學(xué)者來說,都是很向往的一種編程技能乙嘀,但是很多的初學(xué)者卻因為很長一段時間無法進入網(wǎng)絡(luò)編...
    程序員歐陽閱讀 2,017評論 1 37
  • 文章首發(fā)于個人blog歡迎指正補充末购,可聯(lián)系lionsom_lin@qq.com原文地址:《網(wǎng)絡(luò)是怎樣連接的》閱讀整...
    lionsom_lin閱讀 14,159評論 6 31
  • 人最怕,深交后的陌生乒躺,認真后的痛苦招盲,信任后的利用低缩,溫柔后的冷漠嘉冒,親朋間的誤解!所以說有些事情不要太計較,睜一只眼閉...
    420_c644閱讀 166評論 0 0