最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

不為人知的網(wǎng)絡(luò)編程(十三):深入操作系統(tǒng),徹底搞懂127.0.0.1本機(jī)網(wǎng)絡(luò)通信

2021-06-28 15:46 作者:nickkckckck  | 我要投稿

本文作者張彥飛,原題“127.0.0.1 之本機(jī)網(wǎng)絡(luò)通信過(guò)程知多少 ”,首次發(fā)布于“開(kāi)發(fā)內(nèi)功修煉”,轉(zhuǎn)載請(qǐng)聯(lián)系作者。本次有改動(dòng)。

1、引言

繼《你真的了解127.0.0.1和0.0.0.0的區(qū)別?》之后,這是我整理的第2篇有關(guān)本機(jī)網(wǎng)絡(luò)方面的網(wǎng)絡(luò)編程基礎(chǔ)文章。

這次的文章由作者張彥飛原創(chuàng)分享,寫作本文的原因是現(xiàn)在本機(jī)網(wǎng)絡(luò) IO 應(yīng)用非常廣。在 php 中 一般 Nginx 和 php-fpm 是通過(guò) 127.0.0.1 來(lái)進(jìn)行通信的;在微服務(wù)中,由于 side car 模式的應(yīng)用,本機(jī)網(wǎng)絡(luò)請(qǐng)求更是越來(lái)越多。所以,如果能深度理解這個(gè)問(wèn)題在各種網(wǎng)絡(luò)通信應(yīng)用的技術(shù)實(shí)踐中將非常的有意義。

今天咱們就把 127.0.0.1 本機(jī)網(wǎng)絡(luò)通信相關(guān)問(wèn)題搞搞清楚!

為了方便討論,我把這個(gè)問(wèn)題拆分成3問(wèn):

  • 1)127.0.0.1 本機(jī)網(wǎng)絡(luò) IO 需要經(jīng)過(guò)網(wǎng)卡嗎?

  • 2)和外網(wǎng)網(wǎng)絡(luò)通信相比,在內(nèi)核收發(fā)流程上有啥差別?

  • 3)使用 127.0.0.1 能比 192.168.x 更快嗎?

上面這幾個(gè)問(wèn)題,相信包括常期混跡于即時(shí)通訊網(wǎng)的即時(shí)通訊老鳥(niǎo)們?cè)趦?nèi),都是看似很熟悉,但實(shí)則仍然無(wú)法透徹講清楚的話題。這次,我們就來(lái)徹底搞清楚!

(本文同步發(fā)布于:http://www.52im.net/thread-3600-1-1.html)

2、系列文章

本文是系列文章中的第13篇,本系列文章的大綱如下:

《不為人知的網(wǎng)絡(luò)編程(一):淺析TCP協(xié)議中的疑難雜癥(上篇)》

《不為人知的網(wǎng)絡(luò)編程(二):淺析TCP協(xié)議中的疑難雜癥(下篇)》

《不為人知的網(wǎng)絡(luò)編程(三):關(guān)閉TCP連接時(shí)為什么會(huì)TIME_WAIT、CLOSE_WAIT》

《不為人知的網(wǎng)絡(luò)編程(四):深入研究分析TCP的異常關(guān)閉》

《不為人知的網(wǎng)絡(luò)編程(五):UDP的連接性和負(fù)載均衡》

《不為人知的網(wǎng)絡(luò)編程(六):深入地理解UDP協(xié)議并用好它》

《不為人知的網(wǎng)絡(luò)編程(七):如何讓不可靠的UDP變的可靠?》

《不為人知的網(wǎng)絡(luò)編程(八):從數(shù)據(jù)傳輸層深度解密HTTP》

《不為人知的網(wǎng)絡(luò)編程(九):理論聯(lián)系實(shí)際,全方位深入理解DNS》

《不為人知的網(wǎng)絡(luò)編程(十):深入操作系統(tǒng),從內(nèi)核理解網(wǎng)絡(luò)包的接收過(guò)程(Linux篇)》

《不為人知的網(wǎng)絡(luò)編程(十一):從底層入手,深度分析TCP連接耗時(shí)的秘密》

《不為人知的網(wǎng)絡(luò)編程(十二):徹底搞懂TCP協(xié)議層的KeepAlive?;顧C(jī)制》

《不為人知的網(wǎng)絡(luò)編程(十三):深入操作系統(tǒng),徹底搞懂127.0.0.1本機(jī)網(wǎng)絡(luò)通信》(*?本文

3、作為對(duì)比,先看看跨機(jī)網(wǎng)路通信

在開(kāi)始講述本機(jī)通信過(guò)程之前,我們先看看跨機(jī)網(wǎng)絡(luò)通信(以Linux系統(tǒng)內(nèi)核中的實(shí)現(xiàn)為例來(lái)講解)。

3.1 跨機(jī)數(shù)據(jù)發(fā)送

從 send 系統(tǒng)調(diào)用開(kāi)始,直到網(wǎng)卡把數(shù)據(jù)發(fā)送出去,整體流程如下:

在上面這幅圖中,我們看到用戶數(shù)據(jù)被拷貝到內(nèi)核態(tài),然后經(jīng)過(guò)協(xié)議棧處理后進(jìn)入到了?RingBuffer?中。隨后網(wǎng)卡驅(qū)動(dòng)真正將數(shù)據(jù)發(fā)送了出去。當(dāng)發(fā)送完成的時(shí)候,是通過(guò)硬中斷來(lái)通知 CPU,然后清理?RingBuffer。

不過(guò)上面這幅圖并沒(méi)有很好地把內(nèi)核組件和源碼展示出來(lái),我們?cè)購(gòu)拇a的視角看一遍。

等網(wǎng)絡(luò)發(fā)送完畢之后。網(wǎng)卡在發(fā)送完畢的時(shí)候,會(huì)給 CPU 發(fā)送一個(gè)硬中斷來(lái)通知 CPU。收到這個(gè)硬中斷后會(huì)釋放 RingBuffer 中使用的內(nèi)存。

3.2 跨機(jī)數(shù)據(jù)接收

當(dāng)數(shù)據(jù)包到達(dá)另外一臺(tái)機(jī)器的時(shí)候,Linux 數(shù)據(jù)包的接收過(guò)程開(kāi)始了(更詳細(xì)的講解可以看看《深入操作系統(tǒng),從內(nèi)核理解網(wǎng)絡(luò)包的接收過(guò)程(Linux篇)》)。

▲ 上圖引用自《深入操作系統(tǒng),從內(nèi)核理解網(wǎng)絡(luò)包的接收過(guò)程(Linux篇)》

當(dāng)網(wǎng)卡收到數(shù)據(jù)以后,CPU發(fā)起一個(gè)中斷,以通知 CPU 有數(shù)據(jù)到達(dá)。當(dāng)CPU收到中斷請(qǐng)求后,會(huì)去調(diào)用網(wǎng)絡(luò)驅(qū)動(dòng)注冊(cè)的中斷處理函數(shù),觸發(fā)軟中斷。ksoftirqd 檢測(cè)到有軟中斷請(qǐng)求到達(dá),開(kāi)始輪詢收包,收到后交由各級(jí)協(xié)議棧處理。當(dāng)協(xié)議棧處理完并把數(shù)據(jù)放到接收隊(duì)列的之后,喚醒用戶進(jìn)程(假設(shè)是阻塞方式)。

我們?cè)偻瑯訌膬?nèi)核組件和源碼視角看一遍。

3.3 跨機(jī)網(wǎng)絡(luò)通信匯總

關(guān)于跨機(jī)網(wǎng)絡(luò)通信的理解,可以通俗地用下面這張圖來(lái)總結(jié)一下:

4、本機(jī)網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送過(guò)程

在上一節(jié)中,我們看到了跨機(jī)時(shí)整個(gè)網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送過(guò)程 。

在本機(jī)網(wǎng)絡(luò) IO 的過(guò)程中,流程會(huì)有一些差別。為了突出重點(diǎn),本節(jié)將不再介紹整體流程,而是只介紹和跨機(jī)邏輯不同的地方。有差異的地方總共有兩個(gè),分別是路由和驅(qū)動(dòng)程序。

4.1 網(wǎng)絡(luò)層路由

發(fā)送數(shù)據(jù)會(huì)進(jìn)入?yún)f(xié)議棧到網(wǎng)絡(luò)層的時(shí)候,網(wǎng)絡(luò)層入口函數(shù)是?ip_queue_xmit。在網(wǎng)絡(luò)層里會(huì)進(jìn)行路由選擇,路由選擇完畢后,再設(shè)置一些 IP 頭、進(jìn)行一些?netfilter?的過(guò)濾后,將包交給鄰居子系統(tǒng)。

對(duì)于本機(jī)網(wǎng)絡(luò) IO 來(lái)說(shuō),特殊之處在于在?local?路由表中就能找到路由項(xiàng),對(duì)應(yīng)的設(shè)備都將使用?loopback?網(wǎng)卡,也就是我們常見(jiàn)的 lO。

我們來(lái)詳細(xì)看看路由網(wǎng)絡(luò)層里這段路由相關(guān)工作過(guò)程。從網(wǎng)絡(luò)層入口函數(shù)?ip_queue_xmit?看起。

//file: net/ipv4/ip_output.c

intip_queue_xmit(struct sk_buff *skb, struct flowi *fl)

{

?//檢查 socket 中是否有緩存的路由表

?rt = (struct rtable *)__sk_dst_check(sk, 0);

?if(rt == NULL) {

??//沒(méi)有緩存則展開(kāi)查找

??//則查找路由項(xiàng), 并緩存到 socket 中

??rt = ip_route_output_ports(...);

??sk_setup_caps(sk, &rt->dst);

?}

查找路由項(xiàng)的函數(shù)是?ip_route_output_ports,它又依次調(diào)用到?ip_route_output_flow、__ip_route_output_key、fib_lookup。調(diào)用過(guò)程省略掉,直接看?fib_lookup?的關(guān)鍵代碼。

//file:include/net/ip_fib.h

static inline int fib_lookup(struct net *net, const struct flowi4 *flp, struct fib_result *res)

{

?struct fib_table *table;

?

?table = fib_get_table(net, RT_TABLE_LOCAL);

?if(!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))

??return 0;

?

?table = fib_get_table(net, RT_TABLE_MAIN);

?if(!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))

??return 0;

?return -ENETUNREACH;

}

在?fib_lookup?將會(huì)對(duì)?local?和?main?兩個(gè)路由表展開(kāi)查詢,并且是先查 local 后查詢?main。我們?cè)?Linux 上使用命令名可以查看到這兩個(gè)路由表, 這里只看 local 路由表(因?yàn)楸緳C(jī)網(wǎng)絡(luò) IO 查詢到這個(gè)表就終止了)。

#ip route list table local

local10.143.x.y dev eth0 proto kernel scope host src 10.143.x.y

local127.0.0.1 dev lo proto kernel scope host src 127.0.0.1

從上述結(jié)果可以看出,對(duì)于目的是?127.0.0.1?的路由在?local?路由表中就能夠找到了。fib_lookup?工作完成,返回__ip_route_output_key?繼續(xù)。

//file: net/ipv4/route.c

struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)

{

?if(fib_lookup(net, fl4, &res)) {

?}

?if(res.type == RTN_LOCAL) {

??dev_out = net->loopback_dev;

??...

?}

?

?rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);

?return rth;

}

對(duì)于是本機(jī)的網(wǎng)絡(luò)請(qǐng)求,設(shè)備將全部都使用?net->loopback_dev,也就是 lo 虛擬網(wǎng)卡。

接下來(lái)的網(wǎng)絡(luò)層仍然和跨機(jī)網(wǎng)絡(luò) IO 一樣,最終會(huì)經(jīng)過(guò)?ip_finish_output,最終進(jìn)入到 鄰居子系統(tǒng)的入口函數(shù)?dst_neigh_output?中。

本機(jī)網(wǎng)絡(luò) IO 需要進(jìn)行 IP 分片嗎?因?yàn)楹驼5木W(wǎng)絡(luò)層處理過(guò)程一樣會(huì)經(jīng)過(guò) ip_finish_output 函數(shù)。在這個(gè)函數(shù)中,如果 skb 大于 MTU 的話,仍然會(huì)進(jìn)行分片。只不過(guò) lo 的 MTU 比 Ethernet 要大很多。通過(guò) ifconfig 命令就可以查到,普通網(wǎng)卡一般為 1500,而 lO 虛擬接口能有 65535。

在鄰居子系統(tǒng)函數(shù)中經(jīng)過(guò)處理,進(jìn)入到網(wǎng)絡(luò)設(shè)備子系統(tǒng)(入口函數(shù)是 dev_queue_xmit)。

4.2 網(wǎng)絡(luò)設(shè)備子系統(tǒng)

網(wǎng)絡(luò)設(shè)備子系統(tǒng)的入口函數(shù)是?dev_queue_xmit。簡(jiǎn)單回憶下之前講述跨機(jī)發(fā)送過(guò)程的時(shí)候,對(duì)于真的有隊(duì)列的物理設(shè)備,在該函數(shù)中進(jìn)行了一系列復(fù)雜的排隊(duì)等處理以后,才調(diào)用?dev_hard_start_xmit,從這個(gè)函數(shù) 再進(jìn)入驅(qū)動(dòng)程序來(lái)發(fā)送。

在這個(gè)過(guò)程中,甚至還有可能會(huì)觸發(fā)軟中斷來(lái)進(jìn)行發(fā)送,流程如圖:

但是對(duì)于啟動(dòng)狀態(tài)的回環(huán)設(shè)備來(lái)說(shuō)(q->enqueue 判斷為 false),就簡(jiǎn)單多了:沒(méi)有隊(duì)列的問(wèn)題,直接進(jìn)入 dev_hard_start_xmit。接著進(jìn)入回環(huán)設(shè)備的“驅(qū)動(dòng)”里的發(fā)送回調(diào)函數(shù) loopback_xmit,將 skb “發(fā)送”出去。

我們來(lái)看下詳細(xì)的過(guò)程,從網(wǎng)絡(luò)設(shè)備子系統(tǒng)的入口 dev_queue_xmit 看起。

//file: net/core/dev.c

int dev_queue_xmit(struct sk_buff *skb)

{

?q = rcu_dereference_bh(txq->qdisc);

?if(q->enqueue) {//回環(huán)設(shè)備這里為 false

??rc = __dev_xmit_skb(skb, q, dev, txq);

??goto out;

?}

?

?//開(kāi)始回環(huán)設(shè)備處理

?if(dev->flags & IFF_UP) {

??dev_hard_start_xmit(skb, dev, txq, ...);

??...

?}

}

在 dev_hard_start_xmit 中還是將調(diào)用設(shè)備驅(qū)動(dòng)的操作函數(shù)。

//file: net/core/dev.c

int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq)

{

?//獲取設(shè)備驅(qū)動(dòng)的回調(diào)函數(shù)集合 ops

?const struct net_device_ops *ops = dev->netdev_ops;

?

?//調(diào)用驅(qū)動(dòng)的 ndo_start_xmit 來(lái)進(jìn)行發(fā)送

?rc = ops->ndo_start_xmit(skb, dev);

?...

}

4.3 “驅(qū)動(dòng)”程序

對(duì)于真實(shí)的 igb 網(wǎng)卡來(lái)說(shuō),它的驅(qū)動(dòng)代碼都在?drivers/net/ethernet/intel/igb/igb_main.c?文件里。順著這個(gè)路子,我找到了 loopback 設(shè)備的“驅(qū)動(dòng)”代碼位置:drivers/net/loopback.c。

在 drivers/net/loopback.c:

//file:drivers/net/loopback.c

static const struct net_device_ops loopback_ops = {

?.ndo_init????? = loopback_dev_init,

?.ndo_start_xmit = loopback_xmit,

?.ndo_get_stats64 = loopback_get_stats64,

};

所以對(duì)?dev_hard_start_xmit?調(diào)用實(shí)際上執(zhí)行的是?loopback?“驅(qū)動(dòng)” 里的?loopback_xmit。

為什么我把“驅(qū)動(dòng)”加個(gè)引號(hào)呢,因?yàn)?loopback 是一個(gè)純軟件性質(zhì)的虛擬接口,并沒(méi)有真正意義上的驅(qū)動(dòng),它的工作流程大致如圖。

我們?cè)賮?lái)看詳細(xì)的代碼。

//file:drivers/net/loopback.c

static netdev_tx_t loopback_xmit(struct sk_buff *skb, struct net_device *dev)

{

?//剝離掉和原 socket 的聯(lián)系

?skb_orphan(skb);

?

?//調(diào)用netif_rx

?if(likely(netif_rx(skb) == NET_RX_SUCCESS)) {

?}

}

在?skb_orphan?中先是把 skb 上的 socket 指針去掉了(剝離了出來(lái))。

注意:在本機(jī)網(wǎng)絡(luò) IO 發(fā)送的過(guò)程中,傳輸層下面的 skb 就不需要釋放了,直接給接收方傳過(guò)去就行了??偹闶鞘×艘稽c(diǎn)點(diǎn)開(kāi)銷。不過(guò)可惜傳輸層的 skb 同樣節(jié)約不了,還是得頻繁地申請(qǐng)和釋放。

接著調(diào)用?netif_rx,在該方法中 中最終會(huì)執(zhí)行到 enqueue_to_backlog 中(netif_rx -> netif_rx_internal -> enqueue_to_backlog)。

//file: net/core/dev.c

static int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail)

{

?sd = &per_cpu(softnet_data, cpu);

?...

?__skb_queue_tail(&sd->input_pkt_queue, skb);

?...

?____napi_schedule(sd, &sd->backlog);

在?enqueue_to_backlog?把要發(fā)送的 skb 插入?softnet_data->input_pkt_queue?隊(duì)列中并調(diào)用?____napi_schedule?來(lái)觸發(fā)軟中斷。

//file:net/core/dev.c

static inline void ____napi_schedule(struct softnet_data *sd, struct napi_struct *napi)

{

?list_add_tail(&napi->poll_list, &sd->poll_list);

?__raise_softirq_irqoff(NET_RX_SOFTIRQ);

}

只有觸發(fā)完軟中斷,發(fā)送過(guò)程就算是完成了。

5、本機(jī)網(wǎng)絡(luò)數(shù)據(jù)的接收過(guò)程

5.1 主要過(guò)程

在跨機(jī)的網(wǎng)絡(luò)包的接收過(guò)程中,需要經(jīng)過(guò)硬中斷,然后才能觸發(fā)軟中斷。

而在本機(jī)的網(wǎng)絡(luò) IO 過(guò)程中,由于并不真的過(guò)網(wǎng)卡,所以網(wǎng)卡實(shí)際傳輸,硬中斷就都省去了。直接從軟中斷開(kāi)始,經(jīng)過(guò)?process_backlog?后送進(jìn)協(xié)議棧,大體過(guò)程如下圖。

5.2 詳細(xì)過(guò)程

接下來(lái)我們?cè)倏锤敿?xì)一點(diǎn)的過(guò)程。

在軟中斷被觸發(fā)以后,會(huì)進(jìn)入到 NET_RX_SOFTIRQ 對(duì)應(yīng)的處理方法 net_rx_action 中(至于細(xì)節(jié)參見(jiàn)《深入操作系統(tǒng),從內(nèi)核理解網(wǎng)絡(luò)包的接收過(guò)程(Linux篇)》一文中的?4.2 小節(jié))。

//file: net/core/dev.c

static void net_rx_action(struct softirq_action *h){

?while(!list_empty(&sd->poll_list)) {

??work = n->poll(n, weight);

?}

}

我們還記得對(duì)于 igb 網(wǎng)卡來(lái)說(shuō),poll 實(shí)際調(diào)用的是 igb_poll 函數(shù)。

那么 loopback 網(wǎng)卡的 poll 函數(shù)是誰(shuí)呢?由于poll_list 里面是 struct softnet_data 對(duì)象,我們?cè)?net_dev_init 中找到了蛛絲馬跡。

//file:net/core/dev.c

static int __init net_dev_init(void)

{

?for_each_possible_cpu(i) {

??sd->backlog.poll = process_backlog;

?}

}

原來(lái)struct?softnet_data?默認(rèn)的 poll 在初始化的時(shí)候設(shè)置成了?process_backlog?函數(shù),來(lái)看看它都干了啥。

static int process_backlog(struct napi_struct *napi, int quota)

{

?while(){

??while((skb = __skb_dequeue(&sd->process_queue))) {

???__netif_receive_skb(skb);

??}

??//skb_queue_splice_tail_init()函數(shù)用于將鏈表a連接到鏈表b上,

??//形成一個(gè)新的鏈表b,并將原來(lái)a的頭變成空鏈表。

??qlen = skb_queue_len(&sd->input_pkt_queue);

??if(qlen)

???skb_queue_splice_tail_init(&sd->input_pkt_queue, &sd->process_queue);

?}

}

這次先看對(duì)?skb_queue_splice_tail_init?的調(diào)用。源碼就不看了,直接說(shuō)它的作用是把?sd->input_pkt_queue?里的 skb 鏈到?sd->process_queue?鏈表上去。

然后再看?__skb_dequeue,?__skb_dequeue?是從?sd->process_queue?上取下來(lái)包來(lái)處理。這樣和前面發(fā)送過(guò)程的結(jié)尾處就對(duì)上了。發(fā)送過(guò)程是把包放到了?input_pkt_queue?隊(duì)列里,接收過(guò)程是在從這個(gè)隊(duì)列里取出 skb。

最后調(diào)用?__netif_receive_skb?將 skb(數(shù)據(jù)) 送往協(xié)議棧。在此之后的調(diào)用過(guò)程就和跨機(jī)網(wǎng)絡(luò) IO 又一致了。

送往協(xié)議棧的調(diào)用鏈?zhǔn)?__netif_receive_skb => __netif_receive_skb_core => deliver_skb?后 將數(shù)據(jù)包送入到 ip_rcv 中(詳情參見(jiàn)《深入操作系統(tǒng),從內(nèi)核理解網(wǎng)絡(luò)包的接收過(guò)程(Linux篇)》一文中的 4.3 小節(jié))。

網(wǎng)絡(luò)再往后依次是傳輸層,最后喚醒用戶進(jìn)程,這里就不多展開(kāi)了。

6、本機(jī)網(wǎng)絡(luò)通信過(guò)程小結(jié)

我們來(lái)總結(jié)一下本機(jī)網(wǎng)絡(luò)通信的內(nèi)核執(zhí)行流程:

回想下跨機(jī)網(wǎng)絡(luò) IO 的流程是:

好了,回到正題,我們終于可以在單獨(dú)的章節(jié)里回答開(kāi)篇的三個(gè)問(wèn)題啦。

7、開(kāi)篇三個(gè)問(wèn)題的答案

1)問(wèn)題1:127.0.0.1 本機(jī)網(wǎng)絡(luò) IO 需要經(jīng)過(guò)網(wǎng)卡嗎?

通過(guò)本文的敘述,我們確定地得出結(jié)論,不需要經(jīng)過(guò)網(wǎng)卡。即使了把網(wǎng)卡拔了本機(jī)網(wǎng)絡(luò)是否還可以正常使用的。

2)問(wèn)題2:數(shù)據(jù)包在內(nèi)核中是個(gè)什么走向,和外網(wǎng)發(fā)送相比流程上有啥差別?

總的來(lái)說(shuō),本機(jī)網(wǎng)絡(luò) IO 和跨機(jī) IO 比較起來(lái),確實(shí)是節(jié)約了一些開(kāi)銷。發(fā)送數(shù)據(jù)不需要進(jìn) RingBuffer 的驅(qū)動(dòng)隊(duì)列,直接把 skb 傳給接收協(xié)議棧(經(jīng)過(guò)軟中斷)。

但是在內(nèi)核其它組件上可是一點(diǎn)都沒(méi)少:系統(tǒng)調(diào)用、協(xié)議棧(傳輸層、網(wǎng)絡(luò)層等)、網(wǎng)絡(luò)設(shè)備子系統(tǒng)、鄰居子系統(tǒng)整個(gè)走了一個(gè)遍。連“驅(qū)動(dòng)”程序都走了(雖然對(duì)于回環(huán)設(shè)備來(lái)說(shuō)只是一個(gè)純軟件的虛擬出來(lái)的東東)。所以即使是本機(jī)網(wǎng)絡(luò) IO,也別誤以為沒(méi)啥開(kāi)銷。

3)問(wèn)題3:使用 127.0.0.1 能比 192.168.x 更快嗎?

先說(shuō)結(jié)論:我認(rèn)為這兩種使用方法在性能上沒(méi)有啥差別。

我覺(jué)得有相當(dāng)大一部分人都會(huì)認(rèn)為訪問(wèn)本機(jī) Server 的話,用 127.0.0.1 更快。原因是直覺(jué)上認(rèn)為訪問(wèn) IP 就會(huì)經(jīng)過(guò)網(wǎng)卡。

其實(shí)內(nèi)核知道本機(jī)上所有的 IP,只要發(fā)現(xiàn)目的地址是本機(jī) IP 就可以全走 loopback 回環(huán)設(shè)備了。本機(jī)其它 IP 和 127.0.0.1 一樣,也是不用過(guò)物理網(wǎng)卡的,所以訪問(wèn)它們性能開(kāi)銷基本一樣!

附錄:更多網(wǎng)絡(luò)編程系列文章

如果您覺(jué)得本系列文章過(guò)于專業(yè),您可先閱讀《網(wǎng)絡(luò)編程懶人入門》系列文章,該系列目錄如下:

《網(wǎng)絡(luò)編程懶人入門(一):快速理解網(wǎng)絡(luò)通信協(xié)議(上篇)》

《網(wǎng)絡(luò)編程懶人入門(二):快速理解網(wǎng)絡(luò)通信協(xié)議(下篇)》

《網(wǎng)絡(luò)編程懶人入門(三):快速理解TCP協(xié)議一篇就夠》

《網(wǎng)絡(luò)編程懶人入門(四):快速理解TCP和UDP的差異》

《網(wǎng)絡(luò)編程懶人入門(五):快速理解為什么說(shuō)UDP有時(shí)比TCP更有優(yōu)勢(shì)》

《網(wǎng)絡(luò)編程懶人入門(六):史上最通俗的集線器、交換機(jī)、路由器功能原理入門》

《網(wǎng)絡(luò)編程懶人入門(七):深入淺出,全面理解HTTP協(xié)議》

《網(wǎng)絡(luò)編程懶人入門(八):手把手教你寫基于TCP的Socket長(zhǎng)連接》

《網(wǎng)絡(luò)編程懶人入門(九):通俗講解,有了IP地址,為何還要用MAC地址?》

《網(wǎng)絡(luò)編程懶人入門(十):一泡尿的時(shí)間,快速讀懂QUIC協(xié)議》

《網(wǎng)絡(luò)編程懶人入門(十一):一文讀懂什么是IPv6》

《網(wǎng)絡(luò)編程懶人入門(十二):快速讀懂Http/3協(xié)議,一篇就夠!》

本站的《腦殘式網(wǎng)絡(luò)編程入門》也適合入門學(xué)習(xí),本系列大綱如下:

《腦殘式網(wǎng)絡(luò)編程入門(一):跟著動(dòng)畫(huà)來(lái)學(xué)TCP三次握手和四次揮手》

《腦殘式網(wǎng)絡(luò)編程入門(二):我們?cè)谧x寫Socket時(shí),究竟在讀寫什么?》

《腦殘式網(wǎng)絡(luò)編程入門(三):HTTP協(xié)議必知必會(huì)的一些知識(shí)》

《腦殘式網(wǎng)絡(luò)編程入門(四):快速理解HTTP/2的服務(wù)器推送(Server Push)》

《腦殘式網(wǎng)絡(luò)編程入門(五):每天都在用的Ping命令,它到底是什么?》

《腦殘式網(wǎng)絡(luò)編程入門(六):什么是公網(wǎng)IP和內(nèi)網(wǎng)IP?NAT轉(zhuǎn)換又是什么鬼?》

《腦殘式網(wǎng)絡(luò)編程入門(七):面視必備,史上最通俗計(jì)算機(jī)網(wǎng)絡(luò)分層詳解》

《腦殘式網(wǎng)絡(luò)編程入門(八):你真的了解127.0.0.1和0.0.0.0的區(qū)別?》

《腦殘式網(wǎng)絡(luò)編程入門(九):面試必考,史上最通俗大小端字節(jié)序詳解》

以下資料來(lái)自《TCP/IP詳解》,入門者必讀:

《TCP/IP詳解?-?第11章·UDP:用戶數(shù)據(jù)報(bào)協(xié)議》

《TCP/IP詳解?-?第17章·TCP:傳輸控制協(xié)議》

《TCP/IP詳解?-?第18章·TCP連接的建立與終止》

《TCP/IP詳解?-?第21章·TCP的超時(shí)與重傳》

以下系列適合服務(wù)端網(wǎng)絡(luò)編程開(kāi)發(fā)者閱讀:

《高性能網(wǎng)絡(luò)編程(一):?jiǎn)闻_(tái)服務(wù)器并發(fā)TCP連接數(shù)到底可以有多少》

《高性能網(wǎng)絡(luò)編程(二):上一個(gè)10年,著名的C10K并發(fā)連接問(wèn)題》

《高性能網(wǎng)絡(luò)編程(三):下一個(gè)10年,是時(shí)候考慮C10M并發(fā)問(wèn)題了》

《高性能網(wǎng)絡(luò)編程(四):從C10K到C10M高性能網(wǎng)絡(luò)應(yīng)用的理論探索》

《高性能網(wǎng)絡(luò)編程(五):一文讀懂高性能網(wǎng)絡(luò)編程中的I/O模型》

《高性能網(wǎng)絡(luò)編程(六):一文讀懂高性能網(wǎng)絡(luò)編程中的線程模型》

《高性能網(wǎng)絡(luò)編程(七):到底什么是高并發(fā)?一文即懂!》

《從根上理解高性能、高并發(fā)(一):深入計(jì)算機(jī)底層,理解線程與線程池》

《從根上理解高性能、高并發(fā)(二):深入操作系統(tǒng),理解I/O與零拷貝技術(shù)》

《從根上理解高性能、高并發(fā)(三):深入操作系統(tǒng),徹底理解I/O多路復(fù)用》

《從根上理解高性能、高并發(fā)(四):深入操作系統(tǒng),徹底理解同步與異步》

《從根上理解高性能、高并發(fā)(五):深入操作系統(tǒng),理解高并發(fā)中的協(xié)程》

《從根上理解高性能、高并發(fā)(六):通俗易懂,高性能服務(wù)器到底是如何實(shí)現(xiàn)的》

《從根上理解高性能、高并發(fā)(七):深入操作系統(tǒng),一文讀懂進(jìn)程、線程、協(xié)程》

以下系列適合移動(dòng)端資深網(wǎng)絡(luò)通信開(kāi)發(fā)者閱讀:

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(一):通信交換技術(shù)的百年發(fā)展史(上)》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(二):通信交換技術(shù)的百年發(fā)展史(下)》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(三):國(guó)人通信方式的百年變遷》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(四):手機(jī)的演進(jìn),史上最全移動(dòng)終端發(fā)展史》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(五):1G到5G,30年移動(dòng)通信技術(shù)演進(jìn)史》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(六):移動(dòng)終端的接頭人——“基站”技術(shù)》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(七):移動(dòng)終端的千里馬——“電磁波”》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(八):零基礎(chǔ),史上最強(qiáng)“天線”原理掃盲》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(九):無(wú)線通信網(wǎng)絡(luò)的中樞——“核心網(wǎng)”》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十):零基礎(chǔ),史上最強(qiáng)5G技術(shù)掃盲》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十一):為什么WiFi信號(hào)差?一文即懂!》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十二):上網(wǎng)卡頓?網(wǎng)絡(luò)掉線?一文即懂!》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十三):為什么手機(jī)信號(hào)差?一文即懂!》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十四):高鐵上無(wú)線上網(wǎng)有多難?一文即懂!》

《IM開(kāi)發(fā)者的零基礎(chǔ)通信技術(shù)入門(十五):理解定位技術(shù),一篇就夠》

本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

▲ 本文在公眾號(hào)上的鏈接是:點(diǎn)此進(jìn)入。同步發(fā)布鏈接是:http://www.52im.net/thread-3600-1-1.html


不為人知的網(wǎng)絡(luò)編程(十三):深入操作系統(tǒng),徹底搞懂127.0.0.1本機(jī)網(wǎng)絡(luò)通信的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
定兴县| 广宁县| 松潘县| 阿拉尔市| 镇巴县| 天峨县| 林甸县| 定西市| 平潭县| 乡城县| 沙河市| 天等县| 高雄县| 徐汇区| 孝感市| 东台市| 冷水江市| 子长县| 高碑店市| 苍南县| 安阳市| 德阳市| 台南县| 清新县| 丘北县| 武强县| 华阴市| 扶沟县| 江安县| 阜康市| 台东市| 柞水县| 拉孜县| 麻栗坡县| 曲麻莱县| 天祝| 阿坝县| 永吉县| 武穴市| 贵定县| 安仁县|