【Linux網絡編程】網絡基礎

目錄

計算機網絡背景

初識協議

網絡協議

協議分層

OSI七層模型

TCP/IP五層(或四層)模型

再識協議

為什么要有TCP/IP協議?

什么是TCP/IP協議?

重談協議

網絡傳輸基本流程

局域網傳輸流程

跨網絡傳輸流程

Socket編程預備

理解源IP地址與目的IP地址

端口號

傳輸層的典型代表

網絡字節序

Socket編程接口


計算機網絡背景

在沒有網絡之前,計算機B需要計算機A的數據時,是計算機A將數據保存在軟盤中,通過軟盤拷貝給計算機B。這是十分緩慢的。并且,此時各個計算機之間是互相獨立的。

可以再弄一臺計算機充當服務器,當計算機A處理完數據后,將這些數據推送到服務器上,計算機B和計算機C就可以從服務器中獲取數據,處理完后的數據再推送到服務器上。此時就是將多臺計算機連接到了一起,實現了數據共享。沒有了人的參與,效率就高了。

隨著互聯網產生,有了更多的通信需求,就誕生了很多通信公司,研發出了很多通信設備,像路由器、交換機就是通信設備。在一個局域網內部,可以使用交換機連接;兩個局域網可以通過路由器連接,使兩個局域網之間能夠通信。

剛開始的只是局域網。局域網是有問題的,因為只允許在一個局域內通信,太遠的距離是無法通信的,所以就誕生了廣域網。局域網也叫私網,廣域網也叫公網。

結論:網絡的誕生,使計算機之間能夠互相協作。計算機是服務于人的,而人是互相協作的,所以,計算機之間互相協作是必然的。

初識協議

網絡協議

在初識協議部分只是對協議做一個簡單的介紹,讓你對協議有一個初步的認知。

兩臺計算機要進行通信,就必須有一套約定。這個約定分為很多的層級,有些計算機在識別光電信號時,使用的是光電信號的強弱,有些使用的是有無,等等。就是根據光電信號的強弱、有無等,弄成一個0和1的二進制。像計算機、手機、平板等具有計算機屬性的設備,在硬件層面上都必須先做好約定。所以,一個計算機體系要基于網絡搭建起來,就需要先保證在硬件層面上,雙方使用的是同一套約定。

但是,只有硬件上是不夠的,計算機上會有非常多的軟件,這些軟件也必須是一套約定。如大端計算機和小端計算機通信,就需要事先約定;兩臺計算機的顯卡、網卡等供應商不同,OS的版本也不同,如何保證它們遵守一樣的規則?如一臺收到的數據從低字節開始放,一臺從高字節開始放,一臺做4字節對齊,一臺做8字節對齊。

所以,兩臺設備要進行通信時,需要非常多的約定,包括硬件和軟件,不是只規定好01即可,像數據的編碼格式、類型大小、存儲方式等,都需要有約定。此時,就要求計算機內部存在非常多的協議。每個協議,都會有非常細致的規則,協議必須由個人、組織或公司來專門定制這個鄰域的協議

如何讓這些不同廠商之間生產的計算機能夠相互順暢的通信?京就需要有人站出來,約定一個共同的標準,大家都來遵守,這個標準就是網絡協議

實際上,在計算機內部,CPU和內存存在協議,內存與磁盤存在協議,磁盤也有自己的協議。以磁盤為例,我們之前說過,我們要從磁盤讀取,或者向磁盤寫入時,交給磁盤一個LBA地址,磁盤就能找到對應的扇區,從而進行對應的操作。磁盤是如何找到發過來的二進制序列,意思是什么?如是讀,還是寫?是讀到內存,還是讀到哪里?等等。在計算機中,往往需要由工程師為磁盤提供一個驅動程序,這個驅動程序就是使用磁盤的協議的。驅動程序接收到OS的信息后,會將這些信息整合成一個固定大小的二進制序列交給磁盤,如這個二進制序列可能有64個0和1,前2個位代表讀或寫,中間32個位表示若是讀,要讀到哪一一個地址,剩下的位就代表的是LBA地址。這就是協議。所以,不談網絡,單純在計算機體系當中,協議也是無處不在的。

所以,網絡協議只是計算機眾多協議中的一個。網絡協議就是專門為網絡通信設計的約定。網絡協議是一個統稱,是由多個協議組成的。

協議分層

之前在學習OS時,我們知道,計算機的整個體系結構就是分層的。而協議本質也是軟件,在設計上為了更好的進行模塊化,解耦合,也是被設計成為層狀結構的。軟件是分層的。一個軟件,橫向是成模塊的,縱向就是分層的。在面向過程的程序中,將所有的代碼都放在main中,這個軟件就是沒有分層的;現在將main中的部分弄成函數,main函數去調用這些函數,main函數就是頂層調用,這就是軟件分層。基本上所有的計算機語言都有封裝、繼承、多態,封裝、繼承、多態就是支持軟件分層的方式之一。另外,現代計算機語言都會提供容器,并且是面向對象的,因為要先描述,再組織。在計算機世界中,任何問題都可以通過新增一層軟件層來解決。

軟件分層的好處

當兩個人直接使用漢語進行對話時,遵守的是漢語協議。當兩個人通過電話進行對話時,并不是兩個人直接對話,此時是分兩層的。一個人說的話是說給電話的,電話中會有錄音設備,并會根據通信協議將采集到的聲音編碼、加密、打包,完成后,再通過電話線發送給另一臺電話,這一臺電話就會根據通信協議,進行解包、解密、解碼,將聲音從聽筒中放出。站在打電話的人的角度,人會認為是自己直接與對方通信的,因為會忽略底層給我們的支持。

學習網絡時,會有兩個視角:

  • 小白視角:同層協議,直接通信
  • 工程師視角:同層協議,沒有直接通信,是各自使用下層提供的結構能力,完成的通信

高內聚是在同一層,關聯度特別高;低耦合是層與層之間的關聯度特別低。分層是解耦合的有效方式,程序的耦合度低了,可維護性就提高了。所謂可維護性,就是增強了代碼的可讀性,并且當代碼出錯時,更容易排查和修改。類就是高內聚的表現,類與類之間通過接口互相調用就是低耦合的表現。當層與層之間只有接口的調用和被調用關系,此時是最好的。像上面的圖,通信設備層改變了,并不影響語言層;語言層改變了,同樣不影響通信設備層。

在這個例子中,我們的“協議"只有兩層:語言層、通信設備層。但是實際的網絡通信協議,設計的會更加復雜,需要分更多的層。但是通過上面的簡單例子,我們是能理解,分層可以實現解耦合,讓軟件維護的成本更低。

當兩個人在打電話時,會有一個習慣,接通電話后,在說正式的內容前,會“喂”,以確保對方是否能夠聽得到,并且對方聽到“喂“后,也會“喂"一聲,雙方都能聽到后,就開始正式的通信了。這兩聲“喂“實際上也是通信的約定,因為雙方都懂這個“喂“的含義。這也是一種協議,這兩聲“喂”,在通信層面,可以稱之為通信握手。只有握手成功之后,雙方再進行通信。

結論:

  • 協議是一種約定
  • 有了協議之后,軟件在設計上就是分層的

OSI七層模型

OSI模型一共有7層。但是,它既復雜又不實用,所以實際工程中一般只實現其中的4層;所以我們按照TCP/IP四層模型來講解。

為什么標準有七層,而真正實現只有四層呢?

定義標準的人和未來寫代碼實現的人不一定是同一批人。所以,實現未必與標準完全相同。當OSI標準定義出來后,并公開讓別人都可以免費使用,Windows、Linux、華為的手機等都想接入互聯網,Windows就會組織內部的工程師依據OSI標準去寫代碼,在Windows內將網絡實現,Linux等也是一樣。雖然Windows使用的是Windows的網絡,Linux使用的是Linux的網絡,但是它們遵守的都是同一套協議,這就是Windows與Linux,Windows與手機之間能夠互相通信的原因。這些工程師在實現網絡的時候,發現這個OSI標準太復雜了,并且不是很實用,所以,只設計了4層。

TCP/IP五層(或四層)模型

剛剛說過,在計算機鄰域,是有海量的協議的,網絡協議是由非常多的協議構成的TCP/IP協議是一組協議的代名詞,其中包括了非常多的協議,組成了TCP/IP協議族。TCP/IP通訊協議采用了5層的層級結構(實際實現時只有4層),每一層都呼叫它的下一層所提供的網絡來完成自己的需求

物理層:負責光/電信號的傳遞方式.比如現在以太網通用的網線(雙絞線)、早期以太網采用的的同軸電纜(現在主要用于有線電視)、光纖,現在的wifi無線網使用電磁波等都屬于物理層的概念。物理層的能力決定了最大傳輸速率、傳輸距離、抗干擾性等。集線器(Hub)、網卡工作在物理層。

集線器:在物理層,數據是以光電信號的形式傳遞的,以前是通過電纜傳遞光電信號,現在是光纖。在物理設備上傳播時,光電信號是會衰減的,因為會衰減,就必然導致了沒辦法進行遠距離傳輸,為了進行遠距離傳輸,就設計出了集線器,用于放大信號。

數據鏈路層:負責設備之間的數據幀的傳送和識別.例如網卡設備的驅動、幀同步(就是說從網線上檢測到什么信號算作新幀的開始)、沖突檢測(如果檢測到沖突就自動重發)、數據差錯校驗等工作.有以太網、令牌環網,無線LAN等標準。交換機(Switch)工作在數據鏈路層。主要是用來進行局域網通信的。在家里,我們可以通過路由器獲得局域網,家里可能會有幾部手機、幾臺電腦,當一個局域網中主機數過多的話,就需要有一個設備交換機。后序再介紹交換機的原理。

網絡層:負責地址管理和路由選擇.例如在IP協議中,通過IP地址來標識一臺主機,并通過路由表的方式規劃出兩臺主機之間的數據傳輸的線路(路由).路由器(Router)工作在網路層。在網絡層,有一個最典型的設備就是路由器。網絡層主要是將數據通過網絡從一端送到另一端,需要配合IP地址,就可以支持數據包進行長距離轉化了。也就是說,鏈路層主要解決局域網轉化的問題;網絡層主要解決長距離轉化的問題

傳輸層:負責兩臺主機之間的數據傳輸.如傳輸控制協議(TCP),能夠確保數據可靠的從源主機發送到目標主機。從傳輸層開始,就不需要有設備與之對應了。而是由兩端的主機、OS與之對應。

應用層:負責應用程序間溝通,如簡單電子郵件傳輸(SMTP)、文件傳輸協議(FTP)、網絡遠程訪問協議(Telnet)等.我們的網絡編程主要就是針對應用層。

總結:TCP/IP模型將OSI模型的上三層壓縮成了一層,應用層,下四層是一一對應的,導致7層變成了5層。我們寫代碼時,是在應用層寫代碼的。

再識協議

為什么要有TCP/IP協議?

首先,即便是單機,你的計算機內部,其實都是存在協議的。我們知道,每一個計算機都是一個馮諾依曼體系結構,里面會有輸入設備、輸出設備、CPU、內存等,這些設備是通過系統總線連接的,并且它們之間也有各自的協議,系統總線是線,網線也是線,所以,馮諾依曼體系結構就是網絡。在單機情況下,我們從來不會說計算機內存有網絡,因為在計算機內部,這些設備距離非常近,基本上只有幾厘米的距離。但是,兩臺主機之間,相隔的可能就非常遠了。當兩臺主機距離很近,通信是容易的,但是相隔很遠時,此時就會有非常多的問題了。

有了問題,就需要解決問題,否則就無法進行遠距離通信。第一個問題,主機A將數據發送到路由器上,是局域網的問題。第二個問題,要找到主機C,是目標主機定位的問題。第三個問題,數據丟失是丟包重查的問題。這三個問題,是不同性質、不同種類的。對于每一個問題,都應該有一個解決方案。實際上,一種解決方案對應的就是一種協議。因為問題的性質不一樣,所以協議是需要分層的。第一個問題對應的是物理層和鏈路層,第二個問題對應的是網絡層,第三個問題對應的是傳輸層。當我們解決了1、2、3這三個問題后,兩臺主機間就能夠互相通信了。也就是主機C能夠拿到主機A的數據了。但是發送數據只是手段,使用數據才是目的。主機C要如何使用數據呢?這就是應用層的問題了。

結論:存在網絡的終極原因就是傳輸數據時,兩個主機的距離變遠了。因為數據傳輸距離變遠了,就會導致一些問題。而TCP/IP協議就是這些問題的解決方案

什么是TCP/IP協議?

TCP/IP協議的本質是一種解決方案。
TCP/IP協議能分層,前提是因為問題們本身能分層。

重談協議

網絡與OS的關系

注意:網絡是有標準的,即網絡協議。但是OS是沒有標準的,只有一些共同的理論,Linux和Windows具體實現是不一樣的。

網卡就是底層硬件;數據鏈路層屬于驅動程序,所以數據鏈路層一般都在網卡驅動內集成著;網絡層和傳輸層被實現在OS內核中;應用層在OS上層,由用戶實現。

所以,Linux操作系統的實現者在實現時,需要根據TCP/IP協議或OSI模型去設計自己網絡部分的代碼,Windows也是一樣。因為是基于一套標準的,所以一定能通過網絡進行通信。上圖中,兩個操作系統是不同的,但是它們的網絡協議棧是根據TCP/IP協議設計出來的。也正是因此,兩臺不同OS的主機才可以通信。所以,系統的層狀結構幾乎與網絡協議棧的層狀結構是對應的

網絡與OS的關系,結論:OS內需要實現網絡相關的功能,可以理解成網絡是OS的一個模塊或一部分,因為這個模塊所有OS都一樣,所以我們不將其納入到OS中講解,而是單獨拿出來講解。

什么是協議?

應用層、鏈路層、網卡先不管。所以,往后我們說TCP/IP協議主要指的是傳輸層和網絡層。傳輸層和網絡層是實現在內核中的,這兩層中都會有大量的協議,所以OS內是有大量協議的。所以,OS需要管理這些協議,管理方式就是先描述,再組織。所以,協議就是兩個OS為了能夠進行網絡通信,而約定出來的數據結構,一般就是一個結構體。所謂協議,就是通信雙方都認識的結構化的數據類型

OS是C語言寫的,而傳輸層、網絡層是實現在OS內核中的,所以TCP/IP網絡是C語言寫的。Windows和Linux的源代碼是不一樣的,但是網絡部分的代碼一定是一樣的。既然網絡部分的代碼是一樣的,那么Windows定義一個結構體,發送給Linux后,Linux系統一定是看得懂的。一端規定好每個字段的含義,另一端能夠看得懂,這就是雙方的約定。所以,協議實際上就是結構體。未來我們在學習各種具體的協議時,就是在學各個結構體里有什么字段,這個字段的含義是什么。

以一個例子對上面兩個問題進行總結。我們在網上購物時,假設買了一包泡面,我們買的東西是一包泡面,但是我們真正拿到快遞時,是使用一個箱子裝著的,并且箱子上還會有一張快遞單,也就是說我們拿到的東西,會比我們買的東西多一些東西,重點就在這個快遞單。這個快遞單就是一個結構體,它是由發貨的賣家填寫的,并且賣家和買家都是可以看得懂的。這個結構體就是協議。買的是泡面,發的是快遞單+泡面,這個過程叫做封裝。這個快遞單稱為協議報頭。在網絡通信中也是一樣的,現在要給對方發一個"hello",實際發送的東西會在"hello"前多帶一個東西,這個東西就是一個結構體變量,稱為協議報頭。“hello“是實際數據內存,稱為報文。這個協議報頭發送方和接收方都是認識的,此時就可以進行報文的解析和讀取的。

注意:報文并不放在報頭中,而是報頭在前,報文在后的。

網絡傳輸基本流程

局域網傳輸流程

局域網分為多種,以太網就是其中一種。我們以以太網為例。

當兩臺主機都連接同一臺路由器的網絡或同一部手機的熱點時,這兩臺主機就是處于同一個局域網之下的。處于同一個局域網之下的兩臺主機是可以直接通信的。前面主機A和主機C通信的第一步,就是主機A先將數據發送給路由器,而路由器和主機A就是處于同一個局域網之下的,所以處于同一個局域網之下的兩臺主機是可以直接通信的。有了這個認識,我們就可以知道,現在會有很多小的局域網,處于各自局域網之下的主機可以互相通信,要解決的問題就是如何讓這些局域網互相通信呢?路由器就具有這個功能,當然,這個是后面說的。

局域網通信原理,我們以一個例子介紹。當老師和同學在一間教室上課時,老師點名讓一個同學回答問題,老師說這句話時,班級里面所有的同學都能夠聽得見,聽見之后會從這句話中提取出名字,然后跟自己的名字進行對比,發現不是就不響應,若是,則響應,也就是站起來回答問題,回答問題也是同樣如此,這名同學是對著老師回答的,但是全班同學也都能夠聽到。在這個過程中,老師認為他是直接和同學通信的,被點名同學也認為他是直接和老師通信的。在這個例子中,整間教室就是一個大的局域網,老師就是主機A,被點名同學就是主機B。局域網通信的原理就是局域網中一臺主機發出的信息,在這個局域網之下的所有主機都能夠收到,只不過每臺主機都需要有一個標識自身唯一性的地址,這個地址稱為MAC地址。MAC地址是一個48比特位,即6字節,網卡出廠時就已經內置好的序列值。一臺主機發送信息時,會將自己的MAC地址帶上,同時會將目標主機的MAC地址帶上,這兩個MAC地址是放在協議報頭中的。當主機收到信息后,會獲取里面目標主機的MAC地址,并與自己的MAC地址比較,若不同就將這條信息丟棄掉,若相同,則接收。

對于MAC地址,后序談到數據鏈路層時,會詳談MAC幀協議,此處只是知道有MAC地址這個東西即可。實際上,很多設備都有自己的唯一值,包括磁盤、內存,這個唯一值也稱為序列號。但是
MAC地址比較特殊,因為網絡通信時需要他。我們通過指令查看我們的主機的MAC地址。

當然,在Linux下查到的是云服務器的MAC地址。在Windows下是ipconfig /all

這里雖然看到的是主機A、B...,但是要知道其實是一個一個的網絡協議棧在通信。這就與之前學習OS時,每一臺計算機都看成馮諾依曼體系結構是一樣的。因為當前是以太網通信,所以我們只考慮網絡協議棧的下兩層即可,即數據鏈路層和網卡。發消息時,一定是用戶想讓主機A發消息,是用戶層的請求,這個請求一定會貫穿網絡協議棧走到最下面,然后通過硬件發送出去。主機A將消息放到網絡中后,其他主機收到消息一定是硬件先收到消息。其他主機收到消息后,就會在識別目標主機的MAC地址,這個識別工作是數據鏈路層協做的。若不是目標主機,直接丟棄,若是,則將這條信息向上傳遞,直到到達用戶層。所以,主機識別到信息不是自己的,將信息丟棄的行為上層是不知道的。主機E給主機A回消息也是類似的。

回到剛剛老師上課點名的例子。假設老師提問A同學,同時,B同學對C同學說話,C同學對D同學說話..,導致的結果是每個人都無法正常通信。所以,局域網通信,任何時刻只允許存在一份有效的信息在局域網當中。當主機A和主機B都發送消息,就會發生了數據碰撞。為了避免數據碰撞的發生,任何一臺主機在發送消息之后,都會進行碰撞檢測和碰撞避免。主機A發送了消息,自己也是可以收到的,當主機A發現發生了數據碰撞,主機A就會休眠一會,過一會將消息重發,主機A發現自己的消息發生了沖突,這個過程叫做碰撞檢測。過一會再重發一次,這個過程叫做碰撞避免。當主機A和主機B發生數據碰撞時,兩臺主機都要進形碰撞檢測和碰撞避免。兩臺主機都會休眠一會,過一會再重新發。此時局域網中的消息就變少了,其他主機就可以在它們休眠期間進行通信了。一個局域網也叫一個碰撞域

在一個局域網中,主機怎么知道發生了碰撞呢?
主機獲取數據是通過網卡不斷地從局域網中獲取數據。首先,我們要知道網卡怎么知道局域網上有數據。這是純硬件的。發送數據就會有高電壓。當沒有發送數據時,所有網卡的電壓和局域網的電壓是一樣的,一發送數據,局域網的電壓就高了,網絡設計時,就可以讓網卡接收這個高電壓。實際上,CPU和內存互相寫數據時,也是一個道理,它們通過系統總線相連,系統總線中也是有高低電壓的,電壓永遠都是從電壓大的往電壓低的跑。當發生數據碰撞了,電壓就更高了。可以給網卡設置一個閾值,當超過閾值了,就代表發生碰撞了。

所有主機都可以訪問局域網,所以局域網就是一個共享資源,發生了數據碰撞就是數據不一致問題。我們進行碰撞檢測和碰撞避免本質就是在保證局域網唯一被使用。所以,我們可以將局域網當成一個臨界資源。所有豐機是以互斥的形式訪問局域網的,只是這個互斥比較特殊,什么都不管直接發,數據碰撞了再處理。在一個局域網之中,當主機數越多,發發生數據碰撞的概率越高。此時就會造成網速低的現象。

同層之間,都認為自己在和對方同層協議互相通信:

報文=報頭+有效載荷。在應用層,報頭是應用層報頭,有效載荷是“你好";在傳輸層,報頭是傳輸層報頭,有效載荷是應用層報頭+“你好"。在其中一層,就只能識別這一層的報頭,所以拿到數據后,會將這一層的報頭與有效載荷分離,這個分離的過程稱為解包。之前添加報頭的過程稱為封裝。每一層都會有非常多的協議,數據鏈路層將數據鏈路報頭分離之后,如何知道將剩下的有效載荷交給網絡層的哪一個協議呢?

報頭的共性:

  • 報頭與有效載荷分離的問題。也就是說報頭一定需要有一些字段,能夠幫助進行報頭和有效載荷的分離。
  • 報頭內部,必須包含一個字段,叫做交給上層的誰的字段---分用。假設發送數據是從網絡層的IP協議交付給數據鏈路層的,那么數據鏈路層的報頭里面就需要有一個字段IP。當接收數據的主機分離出數據鏈路報頭后,就會進行解析,識別到IP后,就會將其交給網絡層中具體的IP這一層。這個過程稱之為分用

實際上,我們在每一層對報文的叫法是不同的

1. 為什么數據在發送之前要進行封裝?
我們要向網絡中發送數據,必須通過網卡,而網卡是硬件。用戶要將數據寫到網卡中,就必須通過OS,因為OS是軟硬件的管理者,而用戶要訪問OS,就必須通過系統調用。所以用戶想要將數據寫到網卡當中,就必須貫穿整個軟件結構,從系統調用 -> OS內核 -> 驅動程序 -> 硬件,才能將數據寫到網卡上。所以,之所以要進行封裝,是由OS的結構決定的

2.接收到信息的主機,信息自底向上交付的過程一定是通過軟件來做的,也就是通過OS來做的。接收信息的主機的OS怎么知道自己的網卡上有數據了呢?中斷。然后OS執行中斷向量表中的內容,將網卡中的數據搬到OS中,然后進行解包、分用,并一層一層向上交付。

各層的主要協議:

兩臺計算機通過TCP/IP協議通訊的過程如下所示

跨網絡傳輸流程

要想讓處于不同局域網之下的兩臺主機互相通信,就需要將數據包進行跨網絡傳輸了。先來兩個預備工作:了解IP地址、了解以太網與令牌環網。

網絡中的地址管理 - 認識IP地址

IP 協議有兩個版本, IPv4 和IPv6。我們整個的文章,凡是提到IP 協議,沒有特殊說明的,默認都是指IPv4

  • IP地址是在IP協議中,用來標識網絡中不同主機的地址
  • 對于IPv4來說,IP地址是一個4字節,32位的整數;
  • 我們通常也使用"點分十進制"的字符串表示IP地址,例如192.168.0.1;用點分割的每一個數字表示一個字節,范圍是0-255;

可以通過ifconfig來查看主機的IP地址,因為我們使用的是云服務器,實際上是云服務器的IP地址

IP地址會通過"."分成4個部分,每個部分的取值范圍都是0-255。這種IP地址表示方案稱為"點分十進制"。可是查詢到的這個IP地址為什么與登錄云服務器時的IP地址不同呢?登錄云服務器的IP地址是公網IP,查詢到的是內網/私有IP。后序會介紹。

主機間要跨網絡傳輸數據,數據從一臺主機,經過若干臺路由器傳輸到另一臺主機,就會涉及到非常多的IP地址。

MAC地址和IP地址都可以標識主機唯一性,它們有什么區別呢?

舉一個例子幫助理解。我們都知道《西游記》。唐僧的終極目標是從東土大唐到西天。假設唐僧當前剛到達車遲國,那么就會去詢問車遲國國王,想要到達西天,下一站應該去哪里,車遲國國王回答說女兒國,唐僧下一站就會前往女兒國。此時唐僧心里面會有2個地址,第一個地址是從東土大唐到西天,第二個地址是從車遲國到女兒國。唐僧到達女兒國之后,會去詢問女兒國國王,想要到達西天,下一站應該去哪里,女兒國國王回答說祭賽國,唐僧下一站就會前往祭賽國。此時唐僧心里會有2個地址,第一個地址是從東土大唐到西天,第二個地址是從女兒國到祭賽國。可以看到,在唐僧的心中,永遠有2套地址。唐僧從東土大唐到西天的過程當中,會經過非常多的中間站點,而第一個地址是不會發生變化的,而第二個地址是隨著站點的變化而變化的。

  • 東土大唐(源IP地址)? -> 西天(目的IP地址)? ? ? ? ? ?不變
  • 車遲國(源MAC地址) -> 女兒國(目的MAC地址)? 每經過一座城池就改變一次

這一座一座的城池就是一個一個的路由器。城池的國王就是路由算法,詢問車遲國國王要怎么走,這叫做查找路由表,執行路由算法。路由就是做路徑選擇。而路由的依據是目的IP地址。也就是說,下一次到達哪一個路由器,是看目的IP地址的。車遲國和女兒國離得近的意思是位于同一個局域網。所以,數據跨網絡傳輸的本質就是將數據從一個局域網的一臺設備,交給另一臺設備,這另一臺設備再交給和他相鄰的其他設備,局域網或者子網之間消息不斷做轉發,無數個子網串聯起來,最終構成了一個大的網絡拓撲結構,數據長距離傳輸就是經過一個一個子網進行傳輸的。

唐僧當前位于車遲國,既然知道目的地是西天,為什么要詢問車遲國國王下一站到哪里呢?因為局域網通信需要MAC地址。

唐僧每到達一個國家,這個國家的國王只會關心唐僧從哪里來,到哪里去,也就是從東土大唐來到西天去。不會關心上一站是哪里。意思是,一般而言,MAC地址只在局域網中有效。IP地址一般是不會變化的

結論:MAC地址通常用來標識一臺主機在局域網當中的唯一性;IP地址通常用來標識報文在網絡當中的唯一性

以太網與令牌環網

我們要知道,A主機所在的局域網中會有多臺主機,B主機也是一樣。局域網通信的標準中有兩種,大部分情況下使用的都是以太網,所以,以太網就是一種局域網通信標準。上面我們介紹的有碰撞檢測、碰撞避免算法的局域網就是以太網。在局域網中還存在另一個網絡叫做令牌環網。以太網是主機想發送數據直接發,若碰撞了,就休眠,沒有碰撞就發送成功了;令牌環網是只有拿到令牌的主機才能夠發送數據,把一段特定格式的數據當成令牌,持有令牌的主機才能夠發送數據。收消息是不需要令牌的。

A主機所處的局域網是以太網,B主機所處的局域網是令牌環網,它們的工作原理是不一樣的,但是它們的網卡可能是相同或類似的。它們的驅動程序不一樣,控制網卡發出去的消息不一樣。A主機和B主機處于不同的局域網,它們要進行通信就必須要有路由器。路由器是工作在網絡層的一個設備。在主機A看來,路由器就是一臺主機,在主機B看來,路由器也是一臺主機。因為主機A、B都有網絡層,所以主機A、B也有路由功能。因為這個路由器橫跨兩個局域網,所以他要有兩個驅動程序、兩張網卡。主機A向網卡1發消息,主機B向網卡2發消息。所以,路由器要橫跨兩個網絡,就必須要有兩個局域網的接口,以及連接兩端網絡的驅動程序。

有了這兩個概念鋪墊后,來看看數據跨網絡傳輸的流程。

主機A想將數據交給主機B,就必須先將數據交給路由器,交給路由器的過程實際上就是一個局域網通信的過程

主機A為什么將數據交給路由器呢?主機A、B都會有自己的IP地址和MAC地址,路由器會有自己的IP地址,主機A是有網絡層的,所以有路由功能。在同一個局域網當中,設備的IP地址的前綴是一樣的。當數據到達主機A的網絡層時,就會對檢測目標IP地址,并與自己的IP地址比較,若前綴不同,就知道了目標主機與自己一定不屬于同一個網段或者說局域網,此時就將報文交給自己所處局域網的路由器。所以,路由器就是局域網的出口

主機A要將數據發給路由器,就需要知道路由器的MAC地址,主機A怎么知道路由器的MAC地址呢?主機A要連接局域網,就必須先訪問路由器,所以,路由器的MAC地址、IP地址主機A是知道的。實際上,主機的IP地址都是路由器分配的。

在網絡層只是決定要將數據發送給路由器,實際上是數據是網絡層->數據鏈路層->主機A網卡->路由器網卡。所以,主機A向路由器發消息就是一次局域網通信。也就是同樣會有封裝和解包。

路由器拿到主機A發送過來的數據時,一定是網卡先拿到數據,然后會對數據進行解包和分用。路由器的網絡層就可以拿到網絡層的報頭,從而知道了目標主機的IP地址,如果這臺路由器認識這個IP地址,直接發送到這臺主機;若不認識,可以繼續發往下一臺主機。在上圖中,這臺路由器連接了兩個局域網,而目標主機就是另一個局域網當中的主機,所以路由器是認識的。路由器就會將數據向下封裝,然后通過網卡發給主機B。主機B的網卡收到報文后,主機B的數據鏈路層就會判斷MAC地址,發現就是發給自已的,向上分用、解包,到了網絡層,發現目標IP地址就是自己,所以,繼續向上解包、分用,就可以拿到數據了。

可以看到,在跨網絡通信中,所有主機、路由器拿到的網絡層報文是相同的,而鏈路層的報文是各不相同的。這正是MAC地址只在局域網中有效的證明。實際上,網絡層之上的報文也是不變的。

是先有局域網,再有廣域網。所以,局域網的通信方式一定是多樣化的,如以太網、令牌環網、無線網。這些通信方式不同的局域網要如何進行通信呢?我們之前說過,計算機是層狀結構的,任何軟件問題都可以通過新增一層軟件層來解決。雖然各個局域網在底層有各種差異,我們可以新增一個設備路由器,新增一層軟件層叫網絡層,只要不同局域網中的主機支持同一個網絡層協議,就可以屏蔽掉底層網絡的差異。全球內所有想進行跨網絡通信的主機采用的網絡統一稱為IP網絡,IP之下,有差別,IP之上,所有人都一樣。所以,IP,即網絡層是對底層網絡進行屏蔽差異化的一種軟件解決方案。既有MAC地址,又有IP地址,是歷史發展的產物。

IP網絡是基于IP協議構建的數據通信網絡。可以認為數據是從A主機經過無數的網絡層到達B主機

Socket編程預備

理解源IP地址與目的IP地址

往后說IP地址時就不再考慮數據鏈路層了,因為在我們看來,所有的網絡都是IP網絡。IP網絡中,IP地址是用來標識主機唯一性的。實際上,IP是分為公網IP和私有IP的。現在說的是IP是公網IP。

但是這里要思考一個問題:數據傳輸到主機是目的嗎?不是的。因為數據是給人用的。比如:聊天是人在聊天,下載是人在下載,瀏覽網頁是人在瀏覽。

但是人是怎么看到聊天信息的呢?怎么執行下載任務呢?怎么瀏覽網頁信息呢?通過啟動的qq,迅雷,瀏覽器,而啟動的qq,迅雷,瀏覽器都是進程。換句話說,進程是人在系統中的代表,只要把數據給進程,人就相當于就拿到了數據。所以:數據傳輸到主機不是目的,而是手段。到達主機內部,在交給主機內的進程,才是目的

但是系統中,同時會存在非常多的進程,當數據到達目標主機之后,怎么轉發給目標進程?這就要在網絡的背景下,在系統中,標識主機中進程的唯一性。這就需要看端口號了。

端口號

端口號(port)是傳輸層協議的內容。端口號是一個2字節16位的整數;端口號用來標識一個進程,告訴操作系統,當前的這個數據要交給哪一個進程來處理。當我們啟動一個網絡進程時,會從傳輸層申請一個端口號。所以,IP地址用來標識全網中主機的唯一性;端口號用來標識特定主機中進程的唯一性IP地址 + 端口號能夠標識網絡上的某一臺主機的某一個進程

網絡通信的本質:進程間通信。網絡就是這兩個主機的共享資源,兩個進程通過各自的OS來實現共享網絡的效果。IP地址 + 端口號這個組合叫做Socket,套接字。所以,我們通過一臺主機給目標主機發送消息,我們需要有目標主機的IP地址,以及目標進程的端口號,發送的主機是如何知道這兩個的呢?我們要訪問任何一一個網站都需要有域名,域名最終會通過域名解析拿到IP地址;一般客戶端要訪問的某一種應用層服務的端口號都是固定的,若不是固定的,則需要由用戶內置到客戶端當中。

Linux下一切皆文件,所以網卡就是文件,網絡通信的接口也是被集成到文件系統當中的。是文件就需要被OS管理,先描述,再組織。只需要讓struct task_struct的struct file底層指向的方法是網絡接收、發送的方法。所以,應用層通信是使用文件描述符來通信的,類似于讀寫文件。SystemV之所以不重要,就是因為無法集成到網絡當中。所以,網絡也可以進行本地通信。所有進程間通信都可以使用網絡,這樣會有非常強的擴展性。本地通信時就正常通信,當要網絡通信時,直接將進程跨平臺移接到其他主機,代碼就可以改成分布式的代碼。

已經有了進程ID,為什么還要有端口號呢?進程ID屬于是OS的進程管理的內容,如果網絡直接使用,那么OS的進程管理與網絡就是耦合的。所以,網絡里一定要有他獨立的一套機制。

端口號范圍:0-1023:知名端口號,HTTP,FTP,SSH等這些廣為使用的應用層協議,他們的端口號都是固定的;1024-65535:操作系統動態分配的端口號。客戶端程序的端口號,就是由操作系統從這個范圍分配的。

OS拿到報文時,是如何根據端口號將數據交給進程的呢?在OS看來,進程就是一個一個的PCB,傳輸層要將數據交給進程,就是在OS內查找這個PCB,所以,OS可以在OS內核中維護一張端口號的哈希表。簡單一點,我們理解為哈希表下標就是端口號,存儲的內容就是PCB的地址,這樣傳輸層每拿到一個端口號,就能夠找到對應的PCB了。當某一個進程啟動時,就會創建PCB,并申請一個端口號,將PCB的地址填入到這個端口號對應的位置。實際上,OS內也有一張哈希表維護進程PCB與PID的關系。

進程在處理數據時,OS可能在不斷地接收數據,會導致接收的一些數據沒辦法立刻交給進程,等線程處理完了數據,再從OS中獲取數據。這就是一個生產者消費者模型。OS內會有非常多的進程,所以會積壓非常多的數據,這些數據就是報文,OS就需要管理這些報文。就一定要有結構體描述,并組織起來。并由OS維護他,這就是生產者消費者模型的1。

簡述整個過程:網卡接收到報文后,數據鏈路層就會檢測MAC地址,發現是就繼續向上解包、分用,到網絡層會檢測IP地址,發現是就向上解包、分用,到了傳輸層就會將報文放入一個鏈表中,未來進程就可以從這個鏈表中獲取報文了。

傳輸層的典型代表

如果我們了解了系統,也了解了網絡協議棧,我們就會清楚,傳輸層是屬于內核的,那么我們要通過網絡協議棧進行通信,必定調用的是傳輸層提供的系統調用,來進行的網絡通信。傳輸層里用戶最近,所以一般使用的都是傳輸層的接口。也是可以調用網絡層的系統調用的,因為傳輸層、網絡層都屬于OS。往后我們使用到的各種網絡庫,實際上都是對系統調用的封裝。

認識TCP協議與UDP協議

此處我們只是對這兩個協議做一個簡單的介紹。

兩個都是傳輸層的協議TCP在通信時要先建立連接,而UDP不需要TCP提供可靠傳輸,UDP提供不可靠傳輸。TCP會提供可靠傳輸,比方說數據丟包了,會重傳,報文出現重復會去重,出現亂序會排序等。UDP只是給報文添加一個報頭,并交給下一層就完了。可靠傳輸和不可靠傳輸不是這兩個協議的優缺點,而是特點。可靠傳輸要做更多的事,說明TCP協議一定更加復雜,因為復雜,所以應用上就會有更多的約束,資源占用也會更多。選擇TCP還是UDP是需要根據具體場景選擇的。當需要可靠性特別高,比如說轉賬、下單等,使用TCP;當場景對數據丟包等不敏感,比如直播等,就可以選擇UDP。

TCP是面向字節流的,UDP是面向數據報的。字節流:類似于自來水,自來水公司可能給家里提供了1噸,但是我們每次用水,可以只拿1升,1毫升,都可以。字節流內部消息的解釋由用戶自己來解釋。像我們之前往文件中寫入數據時,寫入簡單,但是讀取就非常麻煩。文件寫入就是字節流式寫入,所有的信息都是字節流式的,沒有格式、沒有邊界。怎么讀與怎么發是沒關系的。之前往管道寫入時,可能寫入了100次,但是1次就讀完了,這就是字節流。數據報:我們收到快遞時,快遞是一個一個的,我們不能拿半個。怎么讀,完全取決于怎么發的,這叫做面向數據報。

網絡字節序

我們已經知道,內存中的多字節數據相對于內存地址有大端和小端之分,磁盤文件中的多字節數據相對于文件中的偏移地址也有大端小端之分,網絡數據流同樣有大端小端之分。那么如何定義網絡數據流的地址呢?網絡規定:所有發送到網絡上的數據,都必須是大端的!大部分內容OS會做大小端轉化,但是也有一些必須用戶自己轉化的,如IP地址、端口號,OS提供了一些系統調用來幫助完成轉化。

#include<arpa/inet.h>
// 將 32 位(4 字節)無符號整數從主機字節序轉換為網絡字節序(大端序)
uint32_t htonl(uint32_t hostlong);
// 將 16 位(2 字節)無符號整數從主機字節序轉換為網絡字節序(大端序)
uint16_t htons(uint16_t hostshort);
// 將 16 位(2 字節)無符號整數從網絡字節序轉換回主機字節序
uint16_t ntohs(uint16_t netshort);
// 將 32 位(4 字節)無整數從網絡字節序轉換回主機字節序
uint32_t ntohl(uint32_t netlong);

h代表主機,n代表網絡,是32位,s是16位。16位主要用于轉端口號,32位主要用于轉IP地址。

"192.168.34.45"是字符串風格的IP地址,點分十進制,可讀性高。網絡通信時不能使用字符串,因為字符串太長了,網絡通信一定要是極簡的。因為.之間的都是0-255,所以可以使用char表示,即總共只需要使用4個字節就可以表示一個地址。網絡通信時就會使用這個地址。

端口號也是一樣,網絡傳輸時需要轉為網絡字節序。

Socket編程接口

// 創建 socket 文件描述符 (TCP/UDP, 客戶端 + 服務器)
int socket(int domain, int type, int protocol);
// 綁定端口號 (TCP/UDP, 服務器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 開始監聽 socket (TCP, 服務器)
int listen(int socket, int backlog);
// 接收請求 (TCP, 服務器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建立連接 (TCP, 客戶端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

可以看到,很多接口都需要傳入struct sockaddr類型的參數。

在套接字編程中,套接字的種類有多個:

  • 網絡socket。既可以進行本地通信,也可以進行網絡通信。所以,我們只需要學習網絡socket即可。
  • 本地socket(unix域間socket)。只能進行本地通信。就是一個網絡版本的管道。這里不作介紹。
  • 原始socket。這個不管。

為了進行網絡通信,OS需要提供系統調用。而套接字的種類這么多,如果每種套接字都提供對應的系統調用,那么系統調用的數量就太多了,并且這些接口有很強的相似性。OS為了將接口設計成統一的,就定義處理struct sockaddr。也就是原本需要設計2、3套接口,現在只需要1套接口。

用戶要使用網絡通信時,需要告訴OS三個事情:源IP和目的IP、源端口號和目的端口號、本地通信還是網絡通信。所以,就需要由用戶向OS進行傳參。本地通信或網絡通信都可以使用struct sockaddr_in,本地通信使用struct sockaddr_un。為了統一接口,就設計了struct sockaddr。所有接口都統一使用sockaddr,而真正傳入的可能是sockaddr_in或sockaddr_un,在用戶層強轉一下即可。

雖然接口只有1套,但是在接口內部,仍然是需要是網絡通信,還是本地通信的。所以,這3個結構體的前16位都必須表示同一個內容,稱為地址類型。根據這16位,就可以判斷是做網絡通信,還是本地通信。AF_INET和AF_UNIX就是宏。AF_INET表示網絡通信,AF_UNIX表示本地通信。這就是多態。結構體大小不同是沒事的,因為有類型,OS內部是這3個類型都有定義的。

其實會發現都可以不需要sockaddr,直接在參數中使用void*,因為void*就可以接受任意類型的指針,為什么不用void*呢?首先,void*語義不清楚,使用conststructsockaddr*語義更加清楚。其次,在設計這個接口時,C語言還不支持void*。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/913162.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/913162.shtml
英文地址,請注明出處:http://en.pswp.cn/news/913162.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BlenderBot對話機器人大模型Facebook開發

文章目錄 &#x1f680; BlenderBot 的關鍵特性&#x1f9ea; 版本與改進&#x1f4ca; 應用實例 Blender是攪拌機&#xff0c;果汁機&#xff0c;混合機的意思。 BlenderBot 是由 Facebook AI Research (FAIR) 開發的一種先進的對話生成模型。它旨在通過融合多種對話技能&…

60天python訓練計劃----day59

在之前的學習中&#xff0c;我們層層遞進的介紹了時序模型的發展&#xff0c;從AR到MA到ARMA&#xff0c;再到ARIMA。本質就是把數據處理的操作和模型結合在一起了&#xff0c;實際上昨天提到的季節性差分也可以合并到模型中&#xff0c;讓流程變得更加統一。 季節性差分用S來…

學習日志05 python

我相信事在人為&#xff0c;人定勝天&#xff0c;現在還是在基礎語法上面打轉&#xff0c;還是會提出一些很低級的很基礎的問題&#xff0c;不要著急&#xff0c;波浪式前進、螺旋式上升的過程吧&#xff0c;雖然現在的確是很絕望吧...... 今天要做一個練習&#xff1a;編寫猜…

LiteHub中間件之gzip算法

gzip算法理論部分LZ777算法霍夫曼編碼算法改進型的LZ777算法代碼實現壓縮對象gzip實現運行分析日志查看wireshark抓包查看后臺管理界面查看理論部分 gzip是一種無損壓縮算法&#xff0c;其基礎為Deflate&#xff0c;Deflate是LZ77與哈弗曼編碼的一個組合體。它的基本原理是&…

java+vue+SpringBoo校園失物招領網站(程序+數據庫+報告+部署教程+答辯指導)

源代碼數據庫LW文檔&#xff08;1萬字以上&#xff09;開題報告答辯稿ppt部署教程代碼講解代碼時間修改工具 技術實現 開發語言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot數據庫&#xff1a;mysql 開發工具 JDK版本&#xff1a;JDK1.…

Qt Quick 與 QML(五)qml中的布局

QML布局系統主要分為三大類&#xff1a;錨布局、定位器布局、布局管理器。一、錨布局&#xff08;Anchors&#xff09;通過定義元素與其他元素或父容器的錨點關系實現精確定位&#xff0c;支持動態調整。核心特性屬性??作用??示例?anchors.left左邊緣對齊目標元素anchors.…

【Java|集合類】list遍歷的6種方式

本文主要是總結一下Java集合類中List接口的遍歷方式&#xff0c;以下面的list為例&#xff0c;為大家講解遍歷list的6種方式。 List<Integer> list new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);文章目錄1.直接輸出2.for循環遍…

博弈論基礎-筆記

取石子1 性質一&#xff1a;12345可以確定先手贏&#xff0c;6不論取那個質數都輸&#xff0c;789 10 11可以分別取12345變成6 性質二&#xff1a;6的倍數一定不能取出之后還是6的倍數&#xff08;不能轉換輸態&#xff09; #include <bits/stdc.h> using namespace st…

多任務學習-ESMM

簡介 ESMM&#xff08;Entire Space Multi-task Model&#xff09;是2018年阿里巴巴提出的多任務學習模型。基于共享的特征表達和在用戶整個行為序列空間上的特征提取實現對CTR、CVR的聯合訓練 解決的問題 SSB&#xff08;sample selection bias&#xff09; 如下圖1所示&am…

K8S 集群配置踩坑記錄

系統版本&#xff1a;Ubuntu 22.04.5-live-server-amd64 K8S 版本&#xff1a;v1.28.2 Containerd 版本&#xff1a; 1.7.27 kubelet logs kuberuntime_sandbox.go:72] "Failed to create sandbox for pod" err"rpc error: code Unknown desc failed to cre…

超濾管使用與操作流程-實驗操作013

超濾管使用與操作流程 超濾管&#xff08;或蛋白濃縮管&#xff09;是一種重要的實驗設備&#xff0c;廣泛應用于分離與純化大分子物質&#xff0c;尤其是蛋白質、多糖和核酸等。其工作原理依賴于超濾技術&#xff0c;通過半透膜對分子進行篩分&#xff0c;精準地將大分子物質…

GitHub已破4.5w star,從“零樣本”到“少樣本”TTS,5秒克隆聲音,沖擊傳統錄音棚!

嗨&#xff0c;我是小華同學&#xff0c;專注解鎖高效工作與前沿AI工具&#xff01;每日精選開源技術、實戰技巧&#xff0c;助你省時50%、領先他人一步。&#x1f449;免費訂閱&#xff0c;與10萬技術人共享升級秘籍&#xff01;你是否為錄音成本高、聲音不靈活、又想為多語言…

【中文核心期刊推薦】《遙感信息》

《遙感信息》&#xff08;CN&#xff1a;11-5443/P&#xff09;是一份具有較高學術價值的雙月刊期刊&#xff0c;自創刊以來&#xff0c;憑借新穎的選題和廣泛的報道范圍&#xff0c;兼顧了大眾服務和理論深度&#xff0c;深受學術界和廣大讀者的關注與好評。 該期刊創辦于1986…

uniapp微信小程序css中background-image失效問題

項目場景&#xff1a;提示&#xff1a;這里簡述項目相關背景&#xff1a;在用uniapp做微信小程序的時候&#xff0c;需要一張背景圖&#xff0c;用的是當時做app的時候的框架&#xff0c;但是&#xff0c;在class的樣式中background-image失效了&#xff0c;查了后才知道&#…

iOS App無源碼安全加固實戰:如何對成品IPA實現結構混淆與資源保護

在很多iOS項目交付中&#xff0c;開發者或甲方并不總能拿到應用源碼。例如外包項目交付成品包、歷史項目維護、或者僅負責分發渠道的中間商&#xff0c;都需要在拿到成品ipa文件后對其進行安全加固。然而傳統的源碼級混淆方法&#xff08;如LLVM Obfuscator、Swift Obfuscator&…

Java 中的 ArrayList 和 LinkedList 區別詳解(源碼級理解)

&#x1f680; Java 中的 ArrayList 和 LinkedList 區別詳解&#xff08;源碼級理解&#xff09; 在日常 Java 開發中&#xff0c;ArrayList 和 LinkedList 是我們經常用到的兩種 List 實現。雖然它們都實現了 List 接口&#xff0c;但在底層結構、訪問效率、插入/刪除操作、擴…

使用OpenLayers調用geoserver發布的wms服務

1.前端vue3調用代碼 <template><div><div ref"mapContainer" class"map"></div></div> </template><script setup lang"ts"> import { ref, onMounted } from "vue"; import Map from &quo…

二十七、【測試執行篇】測試計劃:前端一鍵觸發測試 實時狀態追蹤

二十七、【測試執行篇】測試計劃:前端一鍵觸發測試 & 實時狀態追蹤 前言準備工作第一部分:后端 API 確認第二部分:前端實現 - 觸發執行與狀態輪詢第三部分:后端 API 增強第四部分:全面測試總結前言 一個完整的自動化測試流程,從測試用例的創建到報告的生成,最終都需…

60天python訓練營打卡day52

學習目標&#xff1a; 60天python訓練營打卡 學習內容&#xff1a; DAY 52 神經網絡調參指南 知識點回顧&#xff1a; 1.隨機種子 2.內參的初始化 3.神經網絡調參指南 a.參數的分類 b.調參的順序 c.各部分參數的調整心得 作業&#xff1a;對于day’41的簡單cnn&#xff0c;看…

【Modern C++ Part3】Understand-decltype

條款三&#xff1a;理解decltype decltype是一個怪異的發明。給定一個變量名或者表達式&#xff0c;decltype會告訴你這個變量名或表達式的類型。decltype的返回的類型往往也是你期望的。然而有時候&#xff0c;它提供的結果會使開發者極度抓狂而不得參考其他文獻或者在線的Q&…