Linux網絡編程基礎、TCP與UDP、IP與端口等

Linux網絡編程基礎

本文由作者單獨整理歸納,實屬不易,難免存在漏、錯地方,如有發現,請留言指出,定將及時糾正。

1. OSI模型

網絡體系結構指的是網絡的分層結構、以及每層使用的協議的集合。(公司很多部門,每個部門有不同的工作範疇) OSI協議參考模型是典型的網絡體系結構,主要分一下七層:

OSI參考模型
應用層——————<高層>:應用於不同的軟件
表示層——————<高層>:數據格式轉換
會話層——————<高層>:找到傳輸層並調用,進行傳輸

傳輸層——————<低層>:數據打包併發送
網絡層——————<低層>:尋找發送路線
數據鏈路層————<低層>:參數差錯處理、屏蔽硬件差異
物理層——————<低層>:解決不同硬件間的通信

本文並不講全所有的層,只摘取重點
作用:
1.物理層:
負責通過光纖等介質將兩臺計算機連起來,然後在計算機之間通過高低電頻傳送0/1這樣的電信號

2.數據鏈路層:
0/1毫無規則的話計算機看不懂,制定個0/1傳送規則,多少電信號爲一組,每組怎麼標識,以太網協議出現
以太網協議規定:一組電信號構成一個數據包,稱爲幀,由標頭和數據兩部分構成,大小一般爲64 ——1518字節。
幀的長度不固定,標頭長度固定,18字節,每幀單獨發送,數據部分則是具體數據,接受者需要接受的內容

3.MAC地址:
把A的數據通過物理層和數據鏈路層發給另外的誰呢?怎麼區分電腦與電腦呢?
每個進入網絡的計算機都有網卡接口,每個網卡都有一個唯一的地址,這個地址叫MAC地址。
計算機之間的數據傳送,就是通過MAC地址來唯一尋找、傳送的。MAC地址由48字節構成,網卡生產時被唯一標識了

計算機A通過ARP協議得到計算機B的MAC地址,通過的是廣播方式,信息攜帶的IP與自身比較,匹配則反饋,否則忽略

4.網絡層
首先我們要清楚我們所處的網絡由無數個子網構成,網絡就像學校,希望就像班級。

在廣播的時候,也只有同一個子網的計算機可以收到你的信息,那麼,怎麼確定是否在同一子網呢?

  1. 區分MAC地址屬不屬於同一子網的辦法: IP協議
    問題來了:IP協議怎麼區分MAC地址的?
    IP協議所定義的地址稱爲IP地址,IP協議分IPV4 和 IPV6,目前常見IPV4。
    IPV4 由32位二進制數構成,分爲4段,範圍肯定就是0.0.0.0——255.255.255.255咯,沒問題吧?
    IP地址呢又被分爲兩部分,前部分叫網絡部分,後部分叫主機部分,暫時不知道各自佔幾段哈。
    如果A B兩電腦在同一子網,那麼要求AB的網絡部分相同,問題來了,怎麼區分網絡部分和主機各佔多少呢?

  2. 又來一個打輔助的了————子網掩碼,掩碼也是32位二進制,規定掩碼網絡部分二進制全爲1,主機部分全爲0;
    掩碼是有了,怎麼輔助呢?掩碼的特點,網絡部分全爲1,那我們豈不是直到網絡佔多少位了嘛?
    那借用掩碼和自身IP進行與(and)運算,是不是就知道IP地址的網絡佔多少位了?然後兩個IP再比較各自網絡是否相同。

解決了兩臺電腦在同一子網的問題,那如果不在同一子網呢?不在同一子網,我們將數據包發給網關
網關幫我們進行轉發並傳送。

  1. DNS服務器:全世界這麼多網絡,每一個主機有一個IP,能記得住嗎?記不住的,所以就有了DNS服務器
    這玩意就負責解析IP和域名。啥叫域名?www.baidu.com這就叫域名,是不是有了它就方便多了?
    至於到底怎麼解析的,本文暫不介紹,後期補上。
    綜合:通過網絡層,我們是不是就可以找到另外一臺電腦是否和我們處於同一子網了??我們也就知道他的位置了嘛。

5.傳輸層
經過物理層、數據鏈路層、網絡層,我們可以將A的數據傳給B了,但B電腦有100個程序,發給誰呢?
這個時候就安排了一個叫“端口(port)”的傢伙上場了,也就是說我們在A給B傳數據的時候,還要指定端口。
也就是說其實傳輸層就是建立端口到端口的通信,要注意區分網絡層是主機到主機的通信
不要懷疑爲什麼你平時輸IP沒寫端口,因爲那是已經默認了。比如http的傳輸默認端口是80;

6.應用層:應用層就是最接近用戶的,傳輸層傳送了很多數據,各式各樣的格式,看不懂怎麼搞?
不要急,按照一定的數據格式規則進行就好了,它是給軟件提供方接口,讓程序能使用網絡服務。
應用層提供的服務包括文件傳輸、文件管理以及電子郵件的信息處理等。

2. TCP/IP模型

TCP/IP 是一個複雜的協議族,是由一組專業化協議組成。TCP/IP模型將OSI簡化成 4 層,從而有利於實現和高效通信。TCP/IP模型 與 OSI模型

OSI參考模型 --------------------------------------------------------------------TCP/IP模型
應用層——————<高層>:應用於不同的軟件 -------------------------->應用層
表示層——————<高層>:數據格式轉換 -------------------------------> 應用層
會話層——————<高層>:找到傳輸層並調用,進行傳輸 ----------->應用層

傳輸層——————<低層>:數據打包併發送----------------------------->傳輸層
網絡層——————<低層>:尋找發送路線-------------------------------->網絡層
數據鏈路層————<低層>:參數差錯處理、屏蔽硬件差異 ---------->網絡接口層
物理層——————<低層>:解決不同硬件間的通信 ------------------->網絡接口層

  1. 網絡接口層:
    TCP/IP 的最底層,負責將二進制流轉化爲數據幀,並進行數據幀的發送和接收,數據幀是網絡傳輸的基本單元

  2. 網絡層:
    網絡層負責在主機之間的通信中選擇數據包的傳輸路徑,即路由;
    網絡層還負責處理傳入的數據包,驗證其有效性。最後,網絡層還要根據需要發出和接收(ICMP)差錯和控制報文

  3. 傳輸層:
    傳輸層負責實現應用程序之間的通信服務,這種通信又稱爲端到端通信。

  4. 應用層:
    應用層是分層模型的最高層。應用程序使用相應的應用層協議,把封裝好的數據提交給傳輸層或從傳輸層接收數據並處理

3. TCP/IP模型特點

  1. 邊界特點:模型中存在一個地址上的邊界,它將低層網絡的物理地址與網絡層的IP地址分開
    該邊界出現在網絡層與網絡接口層之間。
    1.地址邊界特性:它將IP邏輯地址與底層網絡的硬件地址分開;
    2.操作系統邊界特性:它將網絡應用與協議軟件分開

  2. IP層特性:
    IP層作爲通信子網的最高層,提供無連接的數據包傳輸機制,但IP協議並不能保證IP包傳遞的可靠性

  3. TCP/IP 的可靠性特性:
    TCP 提供面向連接的服務,因爲傳輸層是端到端的,所以TCP/IP的可靠性被稱爲端到端可靠性。

綜合:TCP/IP 的特點就是將不同的低層物理網絡、拓撲結構隱藏起來,向用戶和應用程序提供通用、統一的網絡服務。
TCP/IP 網絡完全撇開了底層物理網絡的特性,是一個統一的整體。

4. TCP

1.TCP :主要應用於賬戶、要求比較高,實時性要求不高的地方。
TCP 嚮應用層提供可靠的、面向連接的數據流傳輸服務,提供高可靠性通信服務。
高可靠性:數據無誤、數據無丟失、數據無時序、數據無重複到達

通過源/目的IP 可以唯一的區分網絡中的兩個設備,再通過源/目的端口可以唯一區分網絡中兩個通信的應用程序

IP:就像身份證號,IPV4是32位的, 4*8,即 4 個0-255數字組成,IP是分配給網卡的。
域名:IP不好記,域名就像姓名,比IP好記。將域名轉成IP,需要DNS服務器的支持。

端口:{ 爲了在一臺設備上可以運行多個程序,人爲的設計了端口(Port)的概念,類似的例子是公司內部的分機號碼。
規定一個設備有216個,也就是65536個端口,每個端口對應一個唯一的程序。
每個網絡程序,無論是客戶端還是服務器端,都對應一個或多個特定的端口號。
由於0-1024之間多被操作系統佔用,所以實際編程時一般採用1024以後的端口號。
}

2.TCP的三次握手
TCP 是面向連接的協議,所謂面向連接就是當計算機雙方通信時,必須先建立連接,然後進行數據通信,最後關閉連接。
TCP 在建立連接時候包括 3 個步驟:
1.A->B:主機A(客戶端)向主機B(服務器)
發送一個包含SYN標誌的TCP報文,並進入SYN_SEND()狀態,等待服務器確認

2.B->A:主機B(服務器)向主機A(客戶端)
主機B在收到客戶端的SYN報文後,將返回一個SYN+ACK的報文表示B的SYN被確認,服務器進入SYN_RECV狀態

3.A->B:主機A(客戶端)向主機B(服務器)
客戶端收到服務器SYN+ACK報文後,向服務器發送確認ACK報文,客戶端和服務器進入ESTABLISHED狀態,完成TCP連接

注意:剛開始客戶端是close狀態,服務器處於listen狀態。

1.第一次握手:客戶端給服務器發送一個SYN報文,並指定客戶端的初始化序列ISN(c),此時客戶端進入SYN-Send狀態
2.第二次握手:服務端收到客戶端發送來的SYN報文後,會將自己的SYN報文進行迴應,並且也會指出自己的ISN(s),同時,還會將客戶端發來的ISN(c)+1作爲ack進行回覆,表明以收到報文,服務器進入SYN-RECD狀態
3.第三次握手:客戶端收到服務器的SYN後,會發送服務器ISN(S)+1作爲ack迴應,表明已收到報文,並進入established狀態
4.服務器收到ack後,也處於established狀態,雙方連接建立。

簡化
第一次握手:客戶端_____SYN(c)(+ISN(c))______>服務器;

第二次握手:服務器_____SYN(s)(+ISN(s)) + ACK(s)(ISN(c)+1)_____>客戶端;

第三次握手:客戶端_____ACK(c)(ISN(s)+1)______>服務器

三次握手的好處
1. 確認雙方的發送能力、接受能力是否正常
2. 指定自己的初始化序列號ISN,爲後面的可靠傳送做準備

注意:1. ISN(初始化序列號)是隨機的,動態生成的。
2. 三次握手過程中,第三次是可以攜帶數據的,第一次第二次不可以攜帶。
想想爲什麼?因爲第一次如果攜帶數據,第一次是客戶端請求服務器,如果有人惡意攻擊服務器,那攻擊裝只需要
在第一次握手中攜帶大量數據,然後不停地攻擊,就可以大量浪費服務器資源了。
第三次可以攜帶,此時都是established狀態,對於客戶端來講,已經知道服務器接收、發送能力都沒問題。

3.TCP的四次揮手
首先,客戶端和服務器都是established狀態,假設客戶端選擇斷開:
1. 第一次揮手:客戶端給服務器發送一個FIN報文,報文指定一個序列號(前面受到信息的最後一個字節的序號+1),
此時,客戶端處於FIN_WAIT1狀態;

  1. 第二次揮手:服務端收到FIN報文後,會發送ACK(客戶端序列號+1)報文,且將服務器的序列號發送
    表明已收到客戶端的報文,此時服務器處於CLOSE_WAIT狀態;
    客戶端收到服務器的FIN報文後,客戶端進入FIN_WAIT2狀態,等待服務器發送最後的數據。

  2. 第三次揮手:服務器向客戶端發送FIN報文,指定自己序列號,然後服務器進入LAST_ACK狀態,等待客戶端迴應

  3. 第四次揮手:客戶端收到FIN報文後,發送ACK(服務器序列號+1)作爲迴應,客戶端進入TIME_WAIT狀態

    簡化
    第一次揮手:客戶端_______> FIN報文(含序列號©) _______> 服務器
    客戶端(established)——————————>客戶端(FIN_WAIT1)(終止等待1)
    服務器(established)——————————>服務器(established)

    第二次揮手:服務器 _______> ACK報文(序列號©+1)+序列號(s) _______> 客戶端
    服務器(established)——————————> 服務器(CLOSE_WAIT)
    客戶端(FIN_WAIT1) ——————————> 客戶端(FIN_WAIT2)(終止等待2)

    第三次揮手:服務器 _______> FIN報文(含序列號(s)) _______> 客戶端
    服務器(CLOSE_WAIT)——————————> 服務器(LAST_ACK)(最後確認)
    客戶端(FIN_WAIT2) ——————————> 客戶端(FIN_WAIT2)

    第四次揮手:客戶端_______> ACK報文(序列號(s)+1) _______> 服務器
    客戶端(FIN_WAIT2) ——————————> 客戶端(TIME_WAIT)(時間等待)
    服務器(LAST_ACK) ——————————> 服務器(CLOSE)

    等時間 = 2*MSL(最長報文段壽命)

    客戶端(TIME_WAIT) ——————————> 客戶端(CLOSE)

4.注意:
1. 此刻TCP還沒關閉,還需要確保服務器收到客戶端ACK後纔會進入CLOSE狀態。
需要多久時間呢進入CLOSE狀態呢?
對於服務器,收到客戶端ACK就關閉,對於客戶端,需要2*MSL(最長報文壽命)才關閉。
所以,服務器比客戶端先關閉。

2.爲什麼客戶端還需要2*MSL時間?
MSL指一個片段在網絡中最大的存活時間,2*MSL就是一個發送和一個回覆所需的最大時間。
如果直到2*MSL,客戶端都沒有再次收到服務端的FIN,那麼客戶端推斷ACK已經被成功接收,則結束TCP連接。

3.爲什麼連接時候是三次握手,斷開要四次揮手?
因爲當服務器當時是listen狀態,客戶端是close狀態,服務器收到客戶端的SYN報文後,
可以直接發送SYN+ACK報文, ACK用來應答,SYN用來同步。
但在斷開連接時候,雙方都是established狀態,客戶端發送FIN報文只是告知服務器客戶端沒有數據發送了(1),
此刻的服務器並不一定沒有數據需要往客戶端發送,可能還有點數據沒發完呢?所以服務器發送的ACK只是告訴
客戶端“我收到你的FIN了”(2),等服務器數據發完了,服務器發送FIN報文(3),然後等客戶端迴應。
客戶端迴應(4)後服務器直接關閉,客戶端還需要等一段時間,如果沒收到FIN則關閉。

4.如果已經建立連接,客戶端突然出故障怎麼辦?
TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。
服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,
若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。
若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。

5. UDP

UDP即用戶數據包協議,是一種面向無連接的、不可靠的傳輸協議,
消耗資源小、速度快,適用於實時性要求高的地方。

UDP在同心之前不需要建立連接,只能用於發送小尺寸數據,
用於廣播、組播、無線網絡,多媒體軟件等
協議選擇:
1. 數據可靠性要求高:TCP
2. 實時性要求高: UDP
3. 網絡狀態好: UDP,網絡狀態不好:TCP

6. 網絡編程基礎

套接字(Socket):套接字是linux下的一種文件,也是一種特殊的I/O接口,也是一種文件描述符。
socket 不僅能實現本地不同進程能夠間的通信,也能通過網絡實現不同主機之間的通信。

想想linux下還有哪些文件,分別用什麼符號代替?
複習一下:
Linux下文件分七種,各自符號如下:( ls -l )
上一篇文章我寫成了6種,將設備混在一起了,現在進行更正。
普通文件 --------------------( - )
目錄文件 -------------------- d
管道文件 -------------------- p
套接字文件 ----------------- s
塊設備文件 ----------------- b
字符設備文件 -------------- c
符號鏈接文件 -------------- l

既然socket是文件描述符,那怎麼獲取socket文件描述符呢?
跟管道一樣,那管道怎麼獲取的呢?( int fd = socket( ) );

socket通過函數創建,並返回一個整形額socket描述符,之後的操作都是利用socket文件描述符

  1. 套接字類型:
    1. 流式套接字(SOCK_STREAM)
    流式套接字提供可靠的、面向連接的通信流,保證數據的可靠性和按序發送。典型: TCP

  2. 數據報套接字(SOCK_DGRAM)
    數據報套接字實現了一種不可靠、無連接的服務。
    數據通過相互獨立的報文發送,且無序。典型:UDP

  3. 原始套接字(SOCK_RAW)
    原始套接字允許對底層協議進行直接訪問,功能強大但不方便。典型: ping命令

2.IP地址:
在前面 OSI模型的網絡層中我們已經講過 IP的基礎知識了,現在進行稍微的延伸一下。

1.IP地址的作用:
IP地址用來表示網絡中的一臺主機。根據協議版本的不同,分爲 IPV4 和 IPV6 兩種。
一個IP地址分爲 2 部分: 1. 網絡部分 2. 主機部分
網絡號和主機號根據掩碼來進行區分。 (IPV4)IP 和掩碼都是32位二進制數,但規則不一樣。

2.IP地址格式轉換:
1. 格式分類:
1.十進制點分形式 : 用戶熟悉的形式:192.168.2.219
2.32位二進制形式 : 網絡傳輸中IP地址的存儲方式

  1. IPV4轉換函數:
    IPV4地址轉換函數有 inet_aton()、inet_addr()、inet_ntoa();
    IPV4和IPV6兼容函數 inet_pton()、inet_ntop();

    1. inet_addrinet_pton()函數是將十進制點分形式轉換爲二進制形式

    2. inet_ntopinet_pton 的反向操作,將二進制地址形式轉爲十進制點分形式

    3. inet_ntoa():將32位網絡字節二進制地址轉換爲點分十進制的字符串、字符串

    4. int inet_addr( const char * strptr)
      參數:strptr: 要轉換的 IP地址字符串("192.168.2.254")
      返回值:1.成功:32位二進制IP地址(網絡字節序) 2.失敗:-1

    5. int inet_pton( int family, const char * src, void * dst)
      參數:family: 1:AF_INET(IPV4協議)
      2:AF_INET6(IPV6協議)
      src: 要轉換的 IP地址字符串
      dst: 存放轉換後的地址的緩衝區
      返回值:1. 成功:0 2.出錯:-1

    6. int inet_ntop( int family, void * src, char * dst, size_t len)
      參數:family: 1:AF_INET(IPV4協議)
      2:AF_INET6(IPV6協議)
      src: 要轉換的二進制IP地址
      dst: 存放十進制地址字符串的緩衝區
      len: 緩衝區的長度
      返回值:1. 成功:dst 2.出錯:NULL

7.端口

端口到底是什麼東西?怎麼用?

  1. 端口(號)是一個無符號整形(unsigned short),取值範圍0--65535(2的16次方-1)
  2. 端口號是系統的一種資源,0--1023一般被系統所調用
  3. TCP 端口號與 UDP端口號互不影響,相互獨立
  4. IP 用來表示網絡中的一臺主機,端口號則可以用來表示主機內部的某個套接字
    即:當創建好一個套接字時,需要將它和某個IP和端口號進行綁定,這樣才能實現端到端通信

8.字節序

字節序又稱主機字節序(HBO),是指計算機在多字節整形數據的存儲方式。
字節序分爲兩種: 1. 大端 2. 小端
1.大端:高位字節存儲在低位地址,低位字節存儲在高位地址
2.小端:高位字節存儲在高位地址,低位字節存儲在低位地址(PC常採用)

大小端是針對多字節存儲的,一個字節不存在大小端。字符串也不存在大小端。

在網絡通信中,統一規定:數據以高位字節優先順序在網絡上傳輸————————大端
所以數據在發送前和接收後都需要在主機字節序和網絡字節序之間轉換

字節序轉換函數:
1. uint16_t htons( unit16_t, hostshort) ——————————主機->服務器<短>
hostshort: 主機字節序的 16bit數據
2. unit16_t ntohs( unit16_t, netshort) ——————————服務器->主機<短>
netshort: 網絡字節序的 16bit數據
3. unit32_t htonl( unit32_t, hostlong) ——————————主機->服務器<長>
hostlong: 主機字節序的 32bit數據
4. unit32_t ntohl( unit32_t, netlong) ——————————服務器->主機<長>
netlong: 網絡字節序的 32bit數據

解釋: h: host; n: network; s: short l: long
成功: 返回轉換後字節序的數值 失敗:-1

通常 16bit的IP端口號使用 htons()ntohs(),而IP地址用 htonl()ntohl()
這四個函數只是使其得到相應的字節序,用戶不需要知道系統主機字節序和網絡字節序是否相等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章