計(jì)算機(jī)網(wǎng)絡(luò)(三)| Socket

Socket簡(jiǎn)介

套接字socket是大多數(shù)程序員都非常熟悉的概念泪幌,它是計(jì)算機(jī)網(wǎng)絡(luò)編程的基礎(chǔ)肴焊,TCP/UDP收發(fā)消息都靠它其屏。我們熟悉的web服務(wù)器底層依賴它,我們用到的MySQL關(guān)系數(shù)據(jù)庫(kù)措译、Redis內(nèi)存數(shù)據(jù)庫(kù)底層依賴它别凤。我們用微信和別人聊天也依賴它,我們玩網(wǎng)絡(luò)游戲時(shí)依賴它领虹,讀者們能夠閱讀這篇文章也是因?yàn)橛兴诒澈竽刂С种W(wǎng)絡(luò)通信闻妓。

Socket傳輸?shù)幕具^(guò)程

當(dāng)客戶端和服務(wù)器使用TCP協(xié)議進(jìn)行通信時(shí),客戶端封裝一個(gè)請(qǐng)求對(duì)象req掠械,將請(qǐng)求對(duì)象req序列化成字節(jié)數(shù)組由缆,然后通過(guò)套接字socket將字節(jié)數(shù)組發(fā)送到服務(wù)器,服務(wù)器通過(guò)套接字socket讀取到字節(jié)數(shù)組猾蒂,再反序列化成請(qǐng)求對(duì)象req均唉,進(jìn)行處理,處理完畢后肚菠,生成一個(gè)響應(yīng)對(duì)應(yīng)res舔箭,將響應(yīng)對(duì)象res序列化成字節(jié)數(shù)組,然后通過(guò)套接字將自己數(shù)組發(fā)送給客戶端蚊逢,客戶端通過(guò)套接字socket讀取到自己數(shù)組层扶,再反序列化成響應(yīng)對(duì)象。

傳輸過(guò)程

通信框架往往可以將序列化的過(guò)程隱藏起來(lái)烙荷,我們所看到的現(xiàn)象就是上圖所示镜会,請(qǐng)求對(duì)象req和響應(yīng)對(duì)象res在客戶端和服務(wù)器之間跑來(lái)跑去。也許你覺得這個(gè)過(guò)程還是挺簡(jiǎn)單的终抽,很好理解戳表,但是實(shí)際上背后發(fā)生的一系列事件超出了你們中大多數(shù)人的想象桶至。通信的真實(shí)過(guò)程要比上面的這張圖復(fù)雜太多。你也許會(huì)問(wèn)匾旭,我們需要了解的那么深入么镣屹,直接拿來(lái)用不就可以了么?在互聯(lián)網(wǎng)技術(shù)服務(wù)行業(yè)工作多年的經(jīng)驗(yàn)告訴我价涝,如果你對(duì)底層機(jī)制不了解女蜈,你就會(huì)不明白為什么對(duì)套接字socket的讀寫會(huì)出現(xiàn)各種奇奇怪怪的問(wèn)題,為什么有時(shí)會(huì)阻塞色瘩,有時(shí)又不阻塞鞭光,有時(shí)候還報(bào)錯(cuò),為什么會(huì)有粘包半包問(wèn)題泞遗,NIO具體又是什么,它是什么特別新鮮的技術(shù)么席覆?對(duì)于這些問(wèn)題的理解都需要你了解底層機(jī)制史辙。

Socket傳輸?shù)木唧w細(xì)節(jié)

我們平時(shí)用到的套接字其實(shí)只是一個(gè)引用(一個(gè)對(duì)象ID),這個(gè)套接字對(duì)象實(shí)際上是放在操作系統(tǒng)內(nèi)核中佩伤。這個(gè)套接字對(duì)象內(nèi)部有兩個(gè)重要的緩沖結(jié)構(gòu)聊倔,一個(gè)是讀緩沖(read buffer),一個(gè)是寫緩沖(write buffer)生巡,它們都是有限大小的數(shù)組結(jié)構(gòu)耙蔑。

當(dāng)我們對(duì)客戶端的socket寫入字節(jié)數(shù)組時(shí)(序列化后的請(qǐng)求消息對(duì)象req),是將字節(jié)數(shù)組拷貝到內(nèi)核區(qū)套接字對(duì)象的write buffer中孤荣,內(nèi)核網(wǎng)絡(luò)模塊會(huì)有單獨(dú)的線程負(fù)責(zé)不停地將write buffer的數(shù)據(jù)拷貝到網(wǎng)卡硬件甸陌,網(wǎng)卡硬件再將數(shù)據(jù)送到網(wǎng)線,經(jīng)過(guò)一些列路由器交換機(jī)盐股,最終送達(dá)服務(wù)器的網(wǎng)卡硬件中钱豁。

同樣,服務(wù)器內(nèi)核的網(wǎng)絡(luò)模塊也會(huì)有單獨(dú)的線程不停地將收到的數(shù)據(jù)拷貝到套接字的read buffer中等待用戶層來(lái)讀取疯汁。最終服務(wù)器的用戶進(jìn)程通過(guò)socket引用的read方法將read buffer中的數(shù)據(jù)拷貝到用戶程序內(nèi)存中進(jìn)行反序列化成請(qǐng)求對(duì)象進(jìn)行處理牲尺。然后服務(wù)器將處理后的響應(yīng)對(duì)象走一個(gè)相反的流程發(fā)送給客戶端,這里就不再具體描述幌蚊。

具體細(xì)節(jié)

Socket發(fā)生阻塞的原因

我們注意到write buffer空間都是有限的谤碳,所以如果應(yīng)用程序往套接字里寫的太快,這個(gè)空間是會(huì)滿的溢豆。一旦滿了蜒简,寫操作就會(huì)阻塞,直到這個(gè)空間有足夠的位置騰出來(lái)漩仙。不過(guò)有了NIO(非阻塞IO)臭蚁,寫操作也可以不阻塞最铁,能寫多少是多少,通過(guò)返回值來(lái)確定到底寫進(jìn)去多少垮兑,那些沒有寫進(jìn)去的內(nèi)容用戶程序會(huì)緩存起來(lái)冷尉,后續(xù)會(huì)繼續(xù)重試寫入。

同樣我們也注意到read buffer的內(nèi)容可能會(huì)是空的系枪。這樣套接字的讀操作(一般是讀一個(gè)定長(zhǎng)的字節(jié)數(shù)組)也會(huì)阻塞雀哨,直到read buffer中有了足夠的內(nèi)容(填充滿字節(jié)數(shù)組)才會(huì)返回。有了NIO私爷,就可以有多少讀多少雾棺,無(wú)須阻塞了。讀不夠的衬浑,后續(xù)會(huì)繼續(xù)嘗試讀取捌浩。

圖片中并沒有展現(xiàn)數(shù)據(jù)的確認(rèn)過(guò)程(ack)。比如當(dāng)寫緩沖的內(nèi)容拷貝到網(wǎng)卡后工秩,是不會(huì)立即從寫緩沖中將這些拷貝的內(nèi)容移除的尸饺,而要等待對(duì)方的ack過(guò)來(lái)之后才會(huì)移除。如果網(wǎng)絡(luò)狀況不好助币,ack遲遲不過(guò)來(lái)浪听,寫緩沖很快就會(huì)滿的。

如果讀緩沖滿了的話眉菱,一般的做法就是丟棄掉緩沖區(qū)的內(nèi)容而且不給對(duì)方ack迹栓,對(duì)方如果發(fā)現(xiàn)ack遲遲沒有來(lái),就會(huì)重發(fā)消息俭缓。那緩沖為什么會(huì)滿克伊?是因?yàn)橄⒔邮辗教幚淼穆l(fā)送方生產(chǎn)的消息太快了,這時(shí)候tcp協(xié)議就會(huì)有個(gè)動(dòng)態(tài)窗口調(diào)整算法來(lái)限制發(fā)送方的發(fā)送速率华坦,使得收發(fā)效率趨于匹配答毫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市季春,隨后出現(xiàn)的幾起案子洗搂,更是在濱河造成了極大的恐慌,老刑警劉巖载弄,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耘拇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宇攻,警方通過(guò)查閱死者的電腦和手機(jī)惫叛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逞刷,“玉大人嘉涌,你說(shuō)我怎么就攤上這事妻熊。” “怎么了仑最?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵扔役,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我警医,道長(zhǎng)亿胸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任预皇,我火速辦了婚禮侈玄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吟温。我一直安慰自己序仙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布鲁豪。 她就那樣靜靜地躺著潘悼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呈昔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天友绝,我揣著相機(jī)與錄音堤尾,去河邊找鬼。 笑死迁客,一個(gè)胖子當(dāng)著我的面吹牛郭宝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掷漱,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粘室,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了卜范?” 一聲冷哼從身側(cè)響起衔统,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎海雪,沒想到半個(gè)月后锦爵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奥裸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年险掀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾宙。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡樟氢,死狀恐怖冈绊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情埠啃,我是刑警寧澤死宣,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站霸妹,受9級(jí)特大地震影響十电,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叹螟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一鹃骂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罢绽,春花似錦畏线、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至明垢,卻和暖如春蚣常,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痊银。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工抵蚊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人溯革。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓贞绳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親致稀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冈闭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353