筆者最近了解了一下Python相關的內容,發現網絡編程部分很是容易可以建立一個UDP本地服務器,正好能夠用來分析一下UDP的請求和響應。在本篇文章中,筆者將給你們介紹下IP、UDP的部份內容。html
聊到網絡協議,咱們經常會想到OSI(Open System Interconnection 開放式系統互聯)七層模型、TCP/IP協議簇,她位於OSI、TCP/IP協議簇哪一層等問題。python
以下圖OSI七層模型及對應的TCP/IP協議簇所示。git
下圖 是OSI七層模型及對應的TCP/IP 協議簇 github
User Datagram Protocol (UDP)編程
UDP is also a transport-layer protocol and is an alternative to TCP. It provides an unreliable datagram connection between applications. Data is transmitted link by link; there is no end-to-end connection. The service provides no guarantees. Data can be lost or duplicated, and datagrams can arrive out of order.bash
UDP也是傳輸層協議,是TCP的替代方案。
它在應用程序之間提供不可靠的數據報鏈接。 數據經過連接傳輸; 沒有端到端的鏈接。
(這裏個人理解是不須要創建鏈接)該服務不保證可靠傳輸。 數據可能丟失或重複,數據報可能無序到達。服務器
Internet Protocol (IP)微信
In terms of the OSI model, IP is a network-layer protocol. It provides a datagram service between applications, supporting both TCP and UDP.網絡
在OSI模型的中,IP是網絡層協議。 它在應用程序之間提供數據報服務,支持TCP和UDP。
筆者在前文提到了要用Python建立一個本地UDP服務器,而且分析UDP的請求及響應過程。這裏筆者使用的是PythonIDE、Mac自帶的終端簡單建立了一個本地UDP服務端和客戶端;
請求響應過程爲:
-> 啓動服務端
-> 啓動客戶端和服務端創建鏈接
-> 客戶端向服務端發送數據'A'
-> 服務端收到數據向客戶端發送'ABCD'。
-> 使用Wireshark對整個請求響應過程進行數據分析。
所用的Python代碼以下:
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license()" for more information.
>>> from socketserver import BaseRequestHandler, UDPServer
>>> class handleRequest(BaseRequestHandler):
def handle(self):
print('Got connection from', self.client_address)
msg, sock = self.request
print('RequestMessage:',msg)
resp = 'ABCD'
print('Response:',resp)
sock.sendto(resp.encode('ascii'), self.client_address)
>>> if __name__ == '__main__':
serv = UDPServer(('', 20000), handleRequest)
serv.serve_forever()
複製代碼
from socket import socket, AF_INET, SOCK_DGRAM
s = socket(AF_INET, SOCK_DGRAM)
s.sendto('A', ('localhost', 20000))
複製代碼
示意圖以下:
筆者結合着IP和UDP的首部示意圖,及Wireshark的請求及響應進行了以下分析:
在分析數據傳輸過程以前,筆者先對下邊會用到的名詞及工具作個簡單說明:
字節
即byte
,比特
即bit
,1個字節(byte)=8個比特(bit)。
ASCII碼:是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其餘西歐語言。它是現今最通用的單字節編碼系統。ASCII碼對照表
舉個例子'A'的ASCII碼爲0x41 基本的16進制、2進制、10進制之間的轉換: -> 16進制0x41 -> 對應2進製爲 0100 0001 -> 對應10進製爲4 * 16 + 1 = 65 在線進制轉換
下圖是請求
的示意圖,可見數據部分是0x41
表示的是十進制的65,即'A'的ASCII碼。
下圖是響應
的示意圖,可見數據部分是0x41424344
表示的是十進制的65 66 67 68,即'ABCD'的ASCII碼。
IP協議所使用的版本
,0100表示的是4即IPv4
IP的首部長度
,0101表示十進制5,不過這裏咱們看到Header Length 爲20字節,緣由是,Head Length的單位是4字節。(即5 * 4 字節 = 20 字節)。首部長度的最大值爲1111即15,首部長度的最大值爲15 * 4字節 = 60字節
。
服務類型
部分,優先級標誌位和服務類型標誌位,被路由器用來進行流量的優先排序。筆者目前不清楚用意,暫不作解釋說明。
下圖爲Total Length(總長度)
顯示爲001d,16進制的d爲13,即13 + 16 = 29。指IP首部和數據報中數據以後的長度,單位爲字節。總長度爲16位,所以數據報的最大長度爲216 - 1 = 65535字節。
標識符
,一個惟一的標識數字,用來識別一個數據報或者被分片數據包的次序。目前筆者對此並不瞭解,暫不作解釋。
下圖爲標記和分段偏移
。
標記
:用來標識一個數據報是不是一組分片數據包的一部分。
Flags:0x0000
,
1比特
;1比特
;表明不分片;1比特
,MF爲0,若是在分片的狀況下,表明這是若干分片中的最後一個;分片偏移
爲0,佔用 13比特
;0 0000 0000 0000分段偏移
:一個數據包是一個分片,這個域中的值就會被用來將數據報以正確順序從新組裝。目前筆者對此並不瞭解,暫不作解釋。
下圖爲Time to live (存活時間)
,用來定義數據報的生存週期,以通過路由器的條數/秒數 進行秒數。目前筆者對此並不瞭解,暫不作解釋。佔用8個比特
,16進制0x40即十進制64。
協議
,用來識別在數據包序列中上層協議數據類型。佔用8
個比特,16進制0x11即十進制17。表明UDP。
首部校驗和
,一個錯誤檢測機制,用來肯定IP首部的內容有沒有被損壞或者篡改。佔用16個比特
。
源IP地址
,即發出數據報的主機的IP地址。佔用32個比特
。16進制的0x7f表明的127,0x7f00 0001 表示127.0.0.1目的IP地址
,數據報目的地的IP地址。佔用32個比特
。16進制的0x7f表明的127,0x7f00 0001 表示127.0.0.1。上述內容就是IP的數據報首部的相關分析,下邊筆者將給你們介紹下UDP的首部的相關內容:
UDP的首部
所示,UDP的首部佔用 64比特,即8個字節
。UDP的源端口
,佔用16比特
。16進製爲0x f432
即爲十進制的62514
。UDP的目標端口
,佔用16比特
。16進製爲0x 4e20
即爲十進制的20000
。
UDP數據報的字節長度
,表示數據報的字節長度。長度佔用UDP首部16比特
。16進製爲0x 0009
即爲十進制的9
(由於UDP首部長度佔8個字節,加上傳輸了一個數據'A'佔用1個字節,共9字節)。UDP數據報的校驗和
,用來確保UDP首部和數據到達時的完整性。校驗和佔用UDP首部16比特
,16進製爲0x fe1c
。目前筆者對這個值並不瞭解,暫不作解釋。數據
,包含被UDP封裝進去的數據,包含應用層協議頭部和用戶發出的數據,咱們傳輸的'A',以下圖,顯示爲16進制的0x41即十進制的65。
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
iOS 多線程之GCD
iOS 多線程之NSOperation
iOS 多線程之NSThread
iOS Winding Rules 纏繞規則
iOS 簽名機制
iOS 掃描二維碼/條形碼
奇舞週刊