日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

图解 | 当我们在读写 Socket 时,我们究竟在读写什么?

發(fā)布時(shí)間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图解 | 当我们在读写 Socket 时,我们究竟在读写什么? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

簡(jiǎn)單過(guò)程

當(dāng)客戶(hù)端和服務(wù)器使用TCP協(xié)議進(jìn)行通信時(shí),客戶(hù)端封裝一個(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ā)送給客戶(hù)端,客戶(hù)端通過(guò)套接字socket讀取到自己數(shù)組,再反序列化成響應(yīng)對(duì)象。

通信框架往往可以將序列化的過(guò)程隱藏起來(lái),我們所看到的現(xiàn)象就是上圖所示,請(qǐng)求對(duì)象req和響應(yīng)對(duì)象res在客戶(hù)端和服務(wù)器之間跑來(lái)跑去。

也許你覺(jué)得這個(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的讀寫(xiě)會(huì)出現(xiàn)各種奇奇乖乖的問(wèn)題,為什么有時(shí)會(huì)阻塞,有時(shí)又不阻塞,有時(shí)候還報(bào)錯(cuò),為什么會(huì)有粘包半包問(wèn)題,NIO具體又是什么,它是什么特別新鮮的技術(shù)么?對(duì)于這些問(wèn)題的理解都需要你了解底層機(jī)制。

細(xì)節(jié)過(guò)程

為了方便大家對(duì)通信底層的理解,我花了些時(shí)間做了下面這個(gè)動(dòng)畫(huà),它并不能完全覆蓋底層細(xì)節(jié)的全貌,但是對(duì)于理解套接字的工作機(jī)制已經(jīng)足夠了。請(qǐng)讀者仔細(xì)觀察這個(gè)動(dòng)畫(huà),后面的講解將圍繞著這個(gè)動(dòng)畫(huà)展開(kāi)。

我們平時(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è)是寫(xiě)緩沖(write buffer),它們都是有限大小的數(shù)組結(jié)構(gòu)。

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

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

阻塞

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

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

ack

那上面這張圖就展現(xiàn)了套接字的全部過(guò)程么?顯然不是,數(shù)據(jù)的確認(rèn)過(guò)程(ack)就完全沒(méi)有展現(xiàn)。比如當(dāng)寫(xiě)緩沖的內(nèi)容拷貝到網(wǎng)卡后,是不會(huì)立即從寫(xiě)緩沖中將這些拷貝的內(nèi)容移除的,而要等待對(duì)方的ack過(guò)來(lái)之后才會(huì)移除。如果網(wǎng)絡(luò)狀況不好,ack遲遲不過(guò)來(lái),寫(xiě)緩沖很快就會(huì)滿(mǎn)的。

包頭

細(xì)心的同學(xué)可能注意到圖中的消息req被拷貝到網(wǎng)卡的時(shí)候變成了大寫(xiě)的REQ,這是為什么呢?因?yàn)檫@兩個(gè)東西已經(jīng)不是完全一樣的了。內(nèi)核的網(wǎng)絡(luò)模塊會(huì)將緩沖區(qū)的消息進(jìn)行分塊傳輸,如果緩沖區(qū)的內(nèi)容太大,是會(huì)被拆分成多個(gè)獨(dú)立的小消息包的。并且還要在每個(gè)消息包上附加上一些額外的頭信息,比如源網(wǎng)卡地址和目標(biāo)網(wǎng)卡地址、消息的序號(hào)等信息,到了接收端需要對(duì)這些消息包進(jìn)行重新排序組裝去頭后才會(huì)扔進(jìn)讀緩沖中。這些復(fù)雜的細(xì)節(jié)過(guò)程就非常難以在動(dòng)畫(huà)上予以呈現(xiàn)了。

速率

還有個(gè)問(wèn)題那就是如果讀緩沖滿(mǎn)了怎么辦,網(wǎng)卡收到了對(duì)方的消息要怎么處理?一般的做法就是丟棄掉不給對(duì)方ack,對(duì)方如果發(fā)現(xiàn)ack遲遲沒(méi)有來(lái),就會(huì)重發(fā)消息。那緩沖為什么會(huì)滿(mǎn)?是因?yàn)橄⒔邮辗教幚淼穆l(fā)送方生產(chǎn)的消息太快了,這時(shí)候tcp協(xié)議就會(huì)有個(gè)動(dòng)態(tài)窗口調(diào)整算法來(lái)限制發(fā)送方的發(fā)送速率,使得收發(fā)效率趨于匹配。如果是udp協(xié)議的話(huà),消息一丟那就徹底丟了。

總結(jié)

以上是生活随笔為你收集整理的图解 | 当我们在读写 Socket 时,我们究竟在读写什么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩高清在线一区 | 亚洲色图1 | 特级黄色录像 | 亚洲一区精品视频在线观看 | 欧美色插 | 两个小y头稚嫩紧窄h文 | 91久久超碰 | 小h片在线观看 | 久久久夜色精品亚洲 | 18成人免费观看视频 | 国产丰满农村老妇女乱 | 中文字幕日韩精品在线 | 日本久久视频 | 精品人妻无码一区二区三区 | 青青色在线视频 | 久久久久亚洲无码 | 丰满人妻综合一区二区三区 | 美女被日网站 | 欧美日韩一二三四 | 日本一区中文字幕 | 亚洲女人18毛片水真多 | av成人免费在线观看 | 日韩免费av在线 | 91爽爽| 免费播放毛片 | 日韩一区二区三区免费视频 | 红桃成人在线 | 91桃色视频| 一级片黑人 | 欧美性猛交xxxx乱大交蜜桃 | 美国av大片| 伊人av在线播放 | 精品一久久 | 葵司av在线 | 中国丰满老太hd | 综合久久av | 成人爽a毛片一区二区免费 日本高清免费看 | 免费成人深夜 | 久久99精品久久久久久国产越南 | 日日操夜夜操天天操 | 日韩爱爱免费视频 | 伊人狠狠干 | 亚洲欧美精品suv | av簧片| 亚洲丝袜视频 | 福利国产片 | 女女百合高h喷汁呻吟玩具 www.亚洲一区 | 中文字幕一区二区三区四区不卡 | 中文字幕在线观看一区 | 亚洲乱码国产乱码精品精大量 | 亚洲第一天堂久久 | 亚洲精品污 | 欧美在线三级 | 国产二区电影 | 亚洲激情一区二区三区 | 成人免费在线网站 | 可以看的av网站 | 在线a级| 国产精品一区麻豆 | 91精品专区 | 欧美日本二区 | 欧美日韩一区二区三区四区五区六区 | 东北老女人av | 亚洲精品一区二区三区在线 | 免费福利视频在线观看 | 午夜xxxxx | 蜜桃av免费看 | 精品色图 | 91在线视频观看 | avtt在线 | 亚洲av色区一区二区三区 | 香蕉视频成人在线 | 国产视频久久久久久久 | 香蕉国产片 | 一呦二呦三呦精品网站 | 国产精品91av| 午夜三级影院 | 大肉大捧一进一出好爽 | 亚洲国产精品成人午夜在线观看 | 国产午夜精品久久久 | 中字幕视频在线永久在线观看免费 | 欧美视频网址 | 亚洲第一网址 | 天天操操操操 | 日韩欧美在线播放 | 国产大片中文字幕 | 九九激情网 | 天天射天天射天天射 | 91久久久久久 | 少女与动物高清版在线观看 | 日韩欧美一区二区三区在线 | 日本xxxxxⅹxxxx69 | av先锋资源| 少妇无码一区二区三区免费 | 亚洲天堂影院 | 小说肉肉视频 | ass日本 | 国产日韩一区二区三区 | 97视频免费在线 |