1. 程式人生 > >Python網路程式設計零基礎2

Python網路程式設計零基礎2

因為基礎內容較多所以內容回顧較多(程式碼放到下面)

  1. 網路效能衡量指標

    • 頻寬:通訊通道上支援的最高資料傳輸頻率
    • 速率:每秒中傳輸多少bits資料
    • 吞吞量:單位時間內通過某個網路資料量
    • 時延:傳輸時延,傳播時延,處理時延,排隊時延
  2. 常用概念

    • 伺服器:提供服務的一方
    • 客戶端:請求服務的一方
    • 通訊:資料傳輸過程
    • 協議:資料組織、編碼、傳輸、校驗、解碼規則
  3. 通訊過程的幾個問題

    • DNS:域名系統,獲得對方IP地址
      域名 ====> IP地址
    • 聯絡上對方:客戶端主動發起連線
    • 通訊過程的正確性:協議來保證
    • 如何正確理解對方的意思:協議來保證
    • 關閉連線
  4. OSI/ISO七層參考模型

    • 應用層:提供使用者服務,負責具體功能的實現
    • 表示層:資料格式的壓縮,優化,加密
    • 會話層:建立應用的連線,選擇合適的傳輸服務
    • *傳輸層:提供傳輸服務(程式之間)
    • 網路層:主機到主機間的資料傳輸
      路由,分段
    • 鏈路層:進行資料交換,控制具體收發
      相鄰主機之間的通訊
    • 物理層:定義機械、物理、電信標準
  5. TCP/IP四層模型

    • 應用層(應用層、表示層、會話層)
    • 傳輸層(傳輸層)
    • 網路層(網路層)
    • 物理鏈路層(資料鏈路層、物理層)
      • 將第一次分為兩層,就是五層模型
  6. IP地址:網路上唯一的地址

    • 組成:32bits

    • 表示方式:點分十進位制的表示方式
      將每8bits分成一組,使用十進位制的數字表示
      11111111 11111111 11111111 11111111
      255.255.255.255

    • 特殊IP
      127.0.0.1 本機IP地址
      0.0.0.0 本機上繫結的所有IP地址
      網路地址 主機地址全部為0
      192.168.1.5
      192.168.1.0
      廣播地址 主機地址部分全部為1
      192.168.1.5
      192.168.1.255

    • 私有地址:預留的一部分地址段,內網使用
      A類:10.0.0.1–10.255.255.254
      B類:172.16.0.1–172.31.255.254
      C類:192.168.0.1–192.168.255.254

  7. 埠號(埠地址):標識不同的服務
    組成:16bits整數
    範圍:1~65535
    系統保留:1~1023 系統保留埠

  8. 傳輸層:程序到程序的資料傳輸

    • TCP:傳輸控制協議
      特點:面向連線,可靠傳輸,流量控制
      適用:資料量大,可靠性要求較高的通訊
      傳輸效率較低

    • UDP:使用者報文協議
      特點:無連線,不可靠傳輸
      適用:資料量小,可靠性要求不高
      傳輸效率較高

  9. 建立、釋放連線過程

    • 建立:三次握手

      • 客戶端發起連線請求,帶上自己的序列號N
      • 伺服器接收連線,產生應答
        N+1:期望收到你下一個包的序號N+1
        K:我自己的序列號K
      • 客戶端傳送確認
        K+1:期望收到你下一個包的序號是K+1
    • 釋放:四次揮手

      • 主動方發起斷開請求
      • 被動方應答,表示準備斷開
      • 被動方發出訊息,表示可以斷開
      • 主動方發出指令,確認斷開
  10. 伺服器、客戶端工作流程

    • 伺服器:
      建立套接字->繫結->監聽->接收->資料傳輸->關閉

    • 客戶端:
      建立套接字->連線->資料傳輸->關閉

  11. 網路套接字(socket)

    • 什麼是套接字
      用於計算機網路通訊的一種介面

    • 套接字的型別

      • 流式套接字(SOCK_STREAM)
        可靠性傳輸、面向連線、資料無差錯傳送
        資料是一個位元組流

      • 資料報套接字
        不可靠、無連線的資料傳輸
        資料是一個一個獨立的資料報,每次傳送都是
        一個數據報

    • 常用方法
      socket() 建立套接字
      bind() 繫結地址
      listen() 監聽
      accept() 接收連線
      send() 傳送
      recv() 接收
      connect() 連線(只能用於客戶端)
      close() 關閉

今天的內容:

1. 服務迴圈接收、客戶端迴圈傳送

將伺服器的recv(), 客戶端的send()放入迴圈中

2. 網路緩衝區

- 每個socket被建立後,都會分配兩個緩衝區
  輸入、輸出緩衝區,分別用於資料收、發
- 當send函式呼叫時,先將資料寫入緩衝區
  send函式就認為傳送成功,並返回
  由TCP協議決定何時從緩衝區傳送到對方
- 當呼叫recv函式接收時,從輸入緩衝區讀取資料
  而不是直接從網路讀取
- 優點:提高讀寫效率,協調收發速度

3. 粘包

- 粘包:多個數據包的資料到達接收緩衝區
        後一個包的頭接著上一個包尾
  例如:
    AAABBB (兩個資料包)

- 什麼時候需要處理粘包
	如果多個數據包資料不同的分組,需要處理
	屬於同一個分組,不需要處理

- 如何處理:
	方式一:在資料包的頭部、尾部增加特殊標記
	   讀取資料的時候,讀取兩個筆記中間的部分
	{2H:AAA:}{2H:BBB:}
	
	方式二:在每個資料包頭增加長度資訊
	        根據長度決定讀取多少個位元組資料
	   例如:頭部採用4個位元組表示長度
	   0003AAA0004BBBB
	   0003:表示該包資料部分長度為3
	       讀取3個位元組:AAA
	   0004:表示該包資料部分長度為4
	       讀取4個位元組:BBBB

**4. UDP套接字 **

1)面向無連線、不可靠傳輸、傳輸效率較高、
   適用於資料量少、可靠性要求不高的資料傳輸

2)UDP工作流程
  - 伺服器
	  建立套接字->繫結地址->收發資料->關閉
	   * 沒有listen,accept過程
  
  - 客戶端
	  建立套接字->傳送、接收資料->關閉

3)UDP套接字的主要函式
  - 建立套接字
    sockfd = socket(AF_INET, SOCK_DGRAM)
    引數:AF_INET   協議族,通過IP、埠
	                地址進行通訊
		  SOCK_DGRAM  套接字型別
		              表示使用者報文套接字
  - 繫結(伺服器端)
    sockfd.bind(address)
	引數:address   繫結地址,由IP、埠構成
  
  - 接收:recvfrom
    data, addr = recvfrom(buffersize)
	  引數:buffersize   每次最多接收的位元組數
	  返回值:data   接收的內容
	          addr   訊息傳送者的地址

  - 傳送:sendto
    n = sendto(data, addr)
	  引數:data   要傳送的資料,bytes格式
	        addr   接收者地址
	  返回值:實際傳送的位元組數

5. TCP和UDP套接字的對比

TCP				UDP
位元組流			資料報
會產生粘包		不會產生粘包
可靠傳輸		不可靠傳輸
需要listen		不需要
    accept
客戶端connect	客戶端不需要connect
recv,send		recvfrom,sendto

6. socket常用的屬性方法

family屬性:地址型別
    AF_INET:傳送方、接收方通過IP、埠來標識
	        IPV4
	AF_UNIX:本地socket,傳送方、接收方位於
	        同一臺機器,地址為檔案路徑
	AF_INET6:IPV6地址型別

type:socket型別
      SOCK_STREAM: 流式socket
	  SOCK_DGRAM: 資料報socket

getpeername(): 獲取連線端的地址資訊
getsockname(): 獲取套接字繫結的地址

fileno(): 獲取套接字的檔案描述符
  檔案描述符:作業系統核心分配的一個非負整數
              每個檔案描述符代表一個檔案
			  當開啟或新建一個檔案
			  核心都會返回一個檔案描述符
			  檔案讀寫、網路socket資料收發、
			  外設操作都是通過檔案描述符進行
   例如:
     - 標準輸入:sys.stdin   0  預設鍵盤
	 - 標準輸出:sys.stdout  1  預設螢幕

setsockopt(level, optname, value)
  功能:設定套接字的選項
        不同的套接字選項代表不同的功能
  引數:
     level: 設定選項的型別
	 optname: 選項型別中的子型別
	 value:為選項設定的值

7. 廣播

  1)什麼是廣播
    - 單播:一點發送、一點接收
	- 多播:也稱組播,一點發送,特定的多個點接收
	- 廣播:一點發送,該網段內容所有的節點接收
	  廣播地址:IP地址的主機地址部分全部為1
	    例如:192.168.1.3,轉換成二進位制
	二進位制:11000000 10101000 00000001 00000011
            |------- 網路地址 -------| |-主機-|
	廣播地址:把主機地址部分全部替換成1
	        11000000 10101000 00000001 11111111
			192.168.1.255

  2)Python中如何實現廣播
     - socket既傳送也接收廣播的時候
	   首先設定SO_BROADCAST選項為1,來支援廣播通訊

   setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
 - 傳送廣播,使用特殊地址broadcast
   而不是標準的IP地址和主機名


基於UDP會話Server程式碼示例

# UDP 服務端 Server

import socket,time
tiMe = time.asctime()[11:19]
# 建立socket連線
sk = socket.socket(type=socket.SOCK_DGRAM)
# 繫結
sk.bind(('127.0.0.1',9999))
print('當前UDP服務端準備就緒',tiMe)
# 傳送訊息迴圈體
while True:
    # 獲取訊息和地址
    msg,addr = sk.recvfrom(1024)
    print('當前基於UDP%s連線已經建立'%addr[0])
    #列印訊息
    print('來自客戶端',addr[0],'的連線:|       ',msg.decode('utf-8'),
        '       |接收時間:',tiMe)
    #傳送訊息
    data = input('輸入要傳送的UDP:')
    sk.sendto(data.encode(),addr)
    # 判斷退出
    if not msg or not data:
        break
# 關閉連線
sk.close()

基於UDP會話Client程式碼示例

#UDP 客戶端Client

import socket,time
tiMe = time.asctime()[11:19]
# 建立套接字
sk = socket.socket(type=socket.SOCK_DGRAM)
# 繫結IP
ip_port = ('127.0.0.1',9999)
print('當前UDP客戶端準備就緒',tiMe)
# 傳送訊息迴圈體
while True:
    # 傳送訊息
    data = input('輸入要傳送的UDP:')
    if not data:
        sk.sendto(''.encode(),ip_port)
        break
    sk.sendto(data.encode(),ip_port)
    # 接收訊息
    msg,addr = sk.recvfrom(1024)
    print('當前基於UDP%s連線已經建立'%addr[0])
    print('來自伺服器',addr[0],'的回覆:|       ',msg.decode('utf-8'),
                '        |接收時間:',tiMe)
    if not msg:
        break
# 關閉連線
sk.close()