1. 程式人生 > >ython3.6入門到高階(全棧) day027 網路通訊協議 osi七層模型

ython3.6入門到高階(全棧) day027 網路通訊協議 osi七層模型

1、網路通訊原理

  網際網路的本質就是一系列的網路協議, 統稱為網際網路協議.

  網際網路協議的功能:定義計算機如何接入internet,以及接入internet的計算機通訊的標準。

  網際網路協議按照功能不同分為osi七層或tcp/ip五層或tcp/ip四層.

   對於tcp\ip 五層協議, 每層執行常見物理裝置有以下幾種:

2、tcp\ip五層協議模型講解 

    我們將應用層,表示層,會話層並作應用層,從tcp/ip五層協議的角度來闡述每層的由來與功能,搞清楚了每層的主要協議就理解了整個網際網路通訊的原理.

    首先,使用者感知到的只是最上面一層應用層,自上而下每層都依賴於下一層,所以我們從最下一層開始切入,比較好理解.

    每層都執行特定的協議,越往上越靠近使用者,越往下越靠近硬體.

  2.1  物理層

    孤立的計算機之間要想一起玩,就必須接入internet,言外之意就是計算機之間必須完成組網.

    物理層功能:主要是基於電器特性發送高低電壓(電訊號),高電壓對應數字1,低電壓對應數字0

2.2  資料鏈路層

    單純的電訊號0和1沒有任何意義,必須規定電訊號多少位一組.

    資料鏈路層的功能:定義了電訊號的分組方式.

    乙太網協議----ethernet

       乙太網協議規定: 一組電訊號組成一個數據包(叫做幀), 每一幀資料由報頭(head)和資料體(date)組成.

       

       報頭(18個位元組): 源Mac地址+目標Mac地址+資料型別

       data資料包含: (最短46位元組,最長1500位元組)

       每組資料包的大小: head長度+data長度=最短64位元組,最長1518位元組,超過最大限制就分片傳送

    通訊方式: 廣播     

      ethernet(乙太網) 採用最原始的方式,廣播的方式進行通訊,即計算機通訊基本靠吼. 這個包會以廣播的方式在傳送端所處的子網內傳輸, 所有主機接收後拆開包, 發現目標ip為自己的, 就響應, 返回自己的mac.

2.3  網路層  

    有了ethernet、mac地址、廣播的傳送方式,世界上的計算機就可以彼此通訊了,問題是世界範圍的網際網路是由一個個彼此隔離的小的區域網組成的,那麼如果所有的通訊都採用乙太網的廣播方式,那麼一臺機器傳送的包全世界都會收到,數以萬計的機器傳送巨量的包不僅會造成網路擁堵癱瘓, 而且資料還不安全.

     網路層功能:引入一套新的地址用來區分不同的廣播域/子網,這套地址即網路地址.

     IP協議

       規定網路地址的協議叫ip協議, 它定義的地址稱之為ip地址, 一個ip地址通常寫成四段十進位制數,例:172.16.10.1.

       IP協議的作用主要有兩個:

        1,是為每一臺計算機分配IP地址

        2, 是確定哪些地址在同一個子網路(通過子網掩碼和and運算), 如果不是一個子網內的, 就通過Arp協議獲取閘道器的Mac地址.

    IP資料包也分為head和data部分, IP資料包直接放入乙太網包的data部分.

      乙太網資料包的”資料”部分, 最長只有1500位元組. 因此, 如果IP資料包超過了1500位元組, 它就需要分割成幾個乙太網資料包, 分開發送了.

    Arp協議

      計算機通訊基本靠吼, 即廣播的方式, 所有上層的包到最後都要封裝上乙太網頭, 然後通過乙太網協議傳送, 乙太網通訊是基於mac的廣播方式實現, 計算機在發包時,獲取自身的mac是容易的, 如何獲取目標主機的mac, 就需要通過arp協議.

    arp協議功能: 廣播的方式傳送資料包, 獲取目標主機的mac地址.

    具體的IP包長什麼樣子? 

    如果不在同一個子網內, 將IP包裡的目標Mac替換成獲取到的閘道器Mac.

  2.4  傳輸層

    網路層的IP幫我們區分子網, 乙太網層的Mac幫我們找到主機, 但是隻找到主機沒用,程式之間進行的溝通啊像QQ、瀏覽器和京東伺服器, 大家使用的都是應用程式, 你的電腦上可能同時開啟qq, 暴風影音等多個應用程式, 那麼我們通過IP和Mac找到了一臺特定的主機,如何標識這臺主機上的應用程式,答案就是埠,埠即應用程式與網絡卡關聯的編號。

    傳輸層功能:建立埠到埠的通訊(端對端通訊)    

      注意: 埠範圍0-65535,0-1023為系統佔用埠

    tcp協議

      TCP把連線作為最基本的物件, 每一條TCP連線都有一個套接字(socket), 埠號拼接到IP地址即構成了套接字, 例如IP地址為192.3.4.16, 而埠號為80, 那麼得到的套接字為192.3.4.16:80.當應用程式希望通過 TCP 與另一個應用程式通訊時, 它會發送一個通訊請求, 這個請求必須被送到一個確切的地址. 在雙方“握手”之後, TCP 將在兩個應用程式之間建立一個全雙工 (full-duplex,雙方都可以收發訊息) 的通訊. 這個全雙工的通訊將佔用兩個計算機之間的通訊線路, 直到它被一方或雙方關閉為止.

    

    TCP(Transmission Control Protocol)可靠的、面向連線的協議(eg:打電話)、傳輸效率低全雙工通訊(傳送快取&接收快取)、面向位元組流。使用TCP的應用:Web瀏覽器;檔案傳輸程式。

    UDP(User Datagram Protocol)不可靠的、無連線的服務,傳輸效率高(傳送前時延小),一對一、一對多、多對一、多對多、面向報文(資料包),盡最大努力服務,無擁塞控制。使用UDP的應用:域名系統 (DNS);視訊流;IP語音(VoIP)。

直接看圖對比其中差異

    tcp的三次握手,四次揮手?(具體見後章節)

  2.5  應用層

    應用層功能: 規定應用程式的資料格式.

     例:tcp協議可以為各種各樣的程式傳遞資料, 比如Email、WWW、FTP等等. 那麼, 必須有不同協議規定電子郵件、網頁、FTP資料的格式, 這些應用程式協議就構成了”應用層”.

 

網路通訊之全流程示意圖

3、socket

   什麼是socket呢?我們經常把socket翻譯為套接字,socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層複雜的操作抽象為幾個簡單的介面供應用層呼叫已實現程序在網路中通訊。

  基於TCP的socket流程圖片

  

 

 

  基於UDP的socket流程圖片

1 # 服務端----------------------------------------------------------------------
 2 import socket
 3 
 4 server = socket.socket()              # 建立一個socket物件
 5 ip_port = ("192.168.15.73",8520)    # 給定服務端的IP和埠
 6 server.bind(ip_port)                 # 服務端繫結IP和埠
 7 server.listen(3)                    # 服務端監聽數量為3個, 即排隊人數為3
 8 while 1:
 9     conn,addr = server.accept()         # 服務端和客戶端之間建立通道
10     info = "服務端提供服務"
11     conn.send(bytes(info,"utf8"))       # 服務端直接用conn 通道來傳輸資料(必須是bytes型別), 客戶端的話通過客戶端物件來傳輸資料.
12 
13     while 1:
14         recv_msg = str(conn.recv(1024),"utf8")     # 1024b 意思是接收到的最大資料長度為1024b
15         print(recv_msg)
16         if recv_msg == "88":
17             break
18         send_msg = input("服務端輸入資訊: ")
19         conn.send(bytes(send_msg,"utf8"))
20     conn.close()
21 
22 server.close()
23 
24 
25 # 客戶端--------------------------------------------------------------------------
26 import socket
27 
28 client = socket.socket()
29 ip_port = ("192.168.15.73",8520)
30 client.connect(ip_port)
31 
32 recv_msg = client.recv(1024)
33 print(str(recv_msg,"utf8"))
34 
35 while 1:
36     info = input("客戶端輸入請求: ")
37     client.send(bytes(info,"utf8"))
38     if info == "88":
39         break
40     recv_msg = client.recv(1024)
41     print(str(recv_msg,"utf8"))
42 
43 client.close()
socket之tcp協議下的客戶端和服務端
1 import socket
 2 
 3 # 服務端
 4 server = socket.socket(type=socket.SOCK_DGRAM)       #  type引數為遵循 udp協議的意思
 5 ip_port = ("127.0.0.1",8520)
 6 server.bind(ip_port)
 7 
 8 recv_msg,addr = server.recvfrom(1024)       # recvfrom接收兩個引數, 資料內容和ip+埠號
 9 print(f"服務端收到來自{addr}的資訊>>>>",str(recv_msg,"utf8"))
10 
11 send_info = "商城資訊balabala......"
12 server.sendto(bytes(send_info,"utf8"),addr)
13 
14 # 客戶端
15 client = socket.socket(type=socket.SOCK_DGRAM)
16 ip_port = ("127.0.0.1",8520)
17 client.sendto(bytes("給我你商城的資訊","utf8"),ip_port)
18 
19 recv_msg,addr = client.recvfrom(1024)
20 print("客戶端收到來自服務端的資訊:",str(recv_msg,"utf8"))
udp協議下的服務端和客戶端

練習:

  寫一個udp協議下的socket簡單聊天工具(類似於QQ)
  1. 服務端
    - 接收客戶端傳送的資訊並作出回覆
  2. 多個客戶端
    - 客戶端向服務端傳送資訊

1 import socket
 2 
 3 # 服務端-------------------------------------------------------------------------
 4 server = socket.socket(type=socket.SOCK_DGRAM)
 5 ip_port = ("192.168.12.42",8520)
 6 server.bind(ip_port)
 7 
 8 while 1:
 9     recv_msg,addr = server.recvfrom(1024)
10     print(f"一條來自客戶端{addr}的訊息: {str(recv_msg,'utf8')}")
11     send_msg = input("輸入回覆內容: ")
12     if not send_msg: continue
13     server.sendto(bytes(send_msg,"utf8"),addr)
14 
15 
16 # 客戶端-------------------------------------------------------------------------
17 client = socket.socket(type=socket.SOCK_DGRAM)
18 qq_name_dic={
19     'taibai':('192.168.12.42',8520),
20     'taihei':('192.168.12.42',8520),
21     'libai':('192.168.12.42',8520),
22     'lihei':('192.168.12.42',8520),
23 }
24 while 1:
25     who = input("請選擇聊天物件[Q退出對話]: ")
26     if who == "Q": break
27     ip_port = qq_name_dic[who]
28     while 1:
29         send_msg = input("輸入聊天內容[Q結束對話]: ")
30         if send_msg == "Q": break
31         if not send_msg or not ip_port: continue
32         client.sendto(bytes(send_msg,"utf8"),ip_port)
33         recv_msg,addr = client.recvfrom(1024)
34         print(str(recv_msg,"utf8"))
udp協議下的聊天工具