Linux中本機和本機Socket通信會走網卡嗎?

Linux中本機和本機通信,例如一個程序請求本機上的一個socket服務,或者請求本機上的一個http介面。請求會經過網卡,走網路嗎?是否linux內核有相關優化呢?


網路層/路由層決定怎麼走。然後就沒有介質訪問控制層/數據鏈路層/物理層什麼事了。

這個其實無需做實驗,把網路協議層的知識複習一遍就知道了。無論是七層協議模型還是四層協議模型都可以清楚的解釋這個事情。


先說結論:不走網卡,不走物理設備,但是走虛擬設備,loopback device環回.

本機的報文的路徑是這樣的:
應用層-&> socket介面 -&> 傳輸層(tcp/udp報文) -&> 網路層 -&> back to 傳輸層 -&> backto socket介面 -.&> 傳回應用程序

在網路層,會在路由表查詢路由,路由表(軟體路由,真正的轉發需要依靠硬體路由,這裡路由表包括快速轉發表和FIB表)初始化時會保存主機路由(host route,or 環迴路由), 查詢(先匹配mask,再匹配ip,localhost路由在路由表最頂端,最優先查到)後發現不用轉發就不用走中斷,不用發送給鏈接層了,不用發送給網路設備(網卡)。像網卡發送接收報文一樣,走相同的接收流程,只不過net device是loopback device,最後發送回應用程序。這一套流程當然和轉發和接收外網報文一樣,都要經過內核協議棧的處理,不同的是本機地址不用掛net device.


我寫一個測試程序,結論是:不需要走網卡。
我生成了一個5G的大文件。同時傳輸的過程中,我把網卡拔掉,最後數據傳輸完畢。
不過這是一個很傻逼的行為,因為直接把網卡拔掉就可以測試。

至於原因 @pansz已經提到了。 雖然我行為是傻逼了點,不過寫這個程序的過程中還是收穫不少呢,因為剛學網路編程,多挖幾個坑還自己還是有好處的。

代碼如下:
生成文件的代碼:

#define SIZE 5000000
#define OPEN_MODE 00777

int main(int argc,char **argv){
srand(time(NULL));
int fd=open("output.txt",O_APPEND|O_RDWR);
int n=0;
char buf[1024]={0};

for(int i=0;i&

Client

int len=0;
while((len=read(fd,sendline,1024))){
if( send(sockfd,sendline,strlen(sendline), 0) &< 0) { printf("send msg error: %s(errno: %d) ", strerror(errno), errno); exit(0); } if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) { perror("recv error"); exit(1); } memset(sendline,0,1024); buf[rec_len] = ""; printf("Received : %s ",buf); } close(sockfd);

Server

void Server::EventLoop(){
int fd=open("re.txt",O_APPEND | O_RDWR);

cout&<&<"waiting for client"s request."&<&(NULL),NULL))==-1){
std::cerr&<&<"acceprt error!"&<&


先說答案,不走物理網卡,和linux內核優化沒半毛錢關係。
wireshark當然可以抓到數據,選定device為lo就行。
從軟體角度說,會走虛擬設備lo,在kernel里route就處理掉,樓上各位已經說清楚。
再多抖點關於loopback的機靈:P
從硬體角度說,ethernet網卡有個PHY的晶元,以MII/RMII協議收發來自CAT-5網線的數據。
在debug硬體時,往往需要設置loopback模式測試網卡是否工作,對於常用的LAN8720有三種loopback模式:near,far,connector:
near-loopback:只測試數字部分,數字信號只會在PHY晶元內TX和RX走一遍,並不會轉成模擬信號再到CAT-5發出去;

far-loopback:只測試模擬部分

connector-loopback: 需要改水晶頭的接線


選擇技術方案要建立在足夠的測試比較上,沒有大量實驗數據支撐的設計都是空中樓閣。有時間來知乎提問你沒時間寫程序比較下127.0.0.1的tcp和管道還有af_unix之間是否有性能差別么?以及windows下的管道及127.0.0.1的tcp是否同樣性能呢?存不存在fast path呢?再翻翻內核實現和自己預想相符么?問來的東西都是淺的,自己真實實驗測量,才能固化成你自己的東西。


有個東西叫本地迴環


環回介面(loopback interface)

TCP/IP協議詳解,卷1,2.7小節,P20

不知道是不是這樣。


不走物理網卡而是走lo這一個虛擬網路介面,抓包選lo介面能抓到。


可以走網卡,也可以不走。(默認是不走)

之前Windows是抓不了不走網卡的包,但有個笨辦法可以抓,就是裝個驅動讓Socket走網卡然後抓,當然速度就慢很多了。。。


高人好多,謝謝大家的分享


你說這個socket和你以為的socket不是一個東西! 計算機網路相關書籍里都有詳細的說明!


《Linux一站式編程》,unix domain socket


印象中不走網卡,因為在走網卡之前會有個什麼列表過濾ip,也就是說127.0.0.1的數據包會直接走回路。


本機socket通訊時,用winshark抓不到任何數據包


推薦閱讀:

TAG:Linux | Socket | 網路編程 |