網(wǎng)絡(luò)數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的發(fā)送和接收處理(網(wǎng)絡(luò)數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的發(fā)送和接收處理方式)
在高級(jí)語(yǔ)言中一般會(huì)使用類似HttpClient、TcpClient、UdpClient等封裝好的API進(jìn)行數(shù)據(jù)的發(fā)送和接收,它們的底層都是基于Socket,而Socket又是基于操作系統(tǒng)內(nèi)核的TCP/IP協(xié)議棧,TCP/IP協(xié)議處理平常就很難接觸到了,再往下內(nèi)核和網(wǎng)卡又是怎么交互的呢?
這篇文章就來介紹網(wǎng)絡(luò)數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的發(fā)送和接收處理過程。
先來看一張示意圖,左側(cè)是數(shù)據(jù)的發(fā)送處理,右側(cè)是數(shù)據(jù)的接收處理,下邊會(huì)按照步驟進(jìn)行說明。
數(shù)據(jù)發(fā)送
1、應(yīng)用程序從內(nèi)存讀取要發(fā)送的數(shù)據(jù)。這里的內(nèi)存是應(yīng)用程序進(jìn)程管理的內(nèi)存,也可稱為用戶空間內(nèi)存。
2、應(yīng)用程序通過Socket接口將讀取到的數(shù)據(jù)發(fā)送到內(nèi)核協(xié)議棧進(jìn)行處理。
3、內(nèi)核中的TCP/IP協(xié)議棧接收到Socket傳遞過來的數(shù)據(jù),進(jìn)行TCP、IP打包,最終以IP數(shù)據(jù)包的格式寫入到內(nèi)核空間的一塊緩存中。數(shù)據(jù)包寫入后會(huì)觸發(fā)一個(gè)軟中斷,通知底層模塊來讀取數(shù)據(jù)。
4、網(wǎng)卡中的DMA單元讀取這些要發(fā)送的數(shù)據(jù),然后發(fā)送到網(wǎng)卡的數(shù)據(jù)鏈路層和物理層,最終發(fā)送到網(wǎng)絡(luò)中進(jìn)行傳輸。
5、DMA讀取數(shù)據(jù)完畢后,會(huì)向CPU發(fā)送一個(gè)中斷,觸發(fā)清理內(nèi)核空間中的發(fā)送數(shù)據(jù)緩存,以便下一次發(fā)送處理。
數(shù)據(jù)接收
1、網(wǎng)卡中的DMA從數(shù)據(jù)鏈路層接收到數(shù)據(jù),然后寫入到內(nèi)核空間的一塊緩存中。
2、緩存寫入完畢后會(huì)發(fā)送一個(gè)CPU中斷,觸發(fā)程序讀取緩存,并發(fā)送到內(nèi)核協(xié)議棧。
3、內(nèi)核中的TCP/IP協(xié)議棧對(duì)接收到的數(shù)據(jù)進(jìn)行解包,去掉IP協(xié)議頭、TCP協(xié)議頭,然后繼續(xù)向上傳遞數(shù)據(jù)。
4、應(yīng)用程序通過Socket接口讀取數(shù)據(jù),這時(shí)讀取到的數(shù)據(jù)就是發(fā)送方發(fā)出來的數(shù)據(jù)了。
5、然后應(yīng)用將這些數(shù)據(jù)寫入到自己的進(jìn)程內(nèi)存中,供進(jìn)一步使用。
圖中的線條和步驟主要描述了數(shù)據(jù)的流轉(zhuǎn),并沒有提供控制邏輯和尋址邏輯的說明,比如DMA向內(nèi)存寫數(shù)據(jù)需要獲取對(duì)應(yīng)的內(nèi)存地址,以及申請(qǐng)總線通道用來傳輸數(shù)據(jù)到內(nèi)存。