python網路-TFTP客戶端開發(25)

来源:https://www.cnblogs.com/Se7eN-HOU/archive/2019/04/22/10747887.html
-Advertisement-
Play Games

一、 TFTP協議介紹 TFTP(Trivial File Transfer Protocol,簡單文件傳輸協議) 是TCP/IP協議族中的一個用來在客戶端與伺服器之間進行簡單文件傳輸的協議 特點: 簡單 占用資源小 適合傳遞小文件 適合在區域網進行傳遞 埠號為69 基於UDP實現 二、TFTP下 ...


一、 TFTP協議介紹

TFTP(Trivial File Transfer Protocol,簡單文件傳輸協議)

是TCP/IP協議族中的一個用來在客戶端與伺服器之間進行簡單文件傳輸的協議

特點:

  • 簡單
  • 占用資源小
  • 適合傳遞小文件
  • 適合在區域網進行傳遞
  • 埠號為69
  • 基於UDP實現

二、TFTP下載過程

TFTP伺服器預設監聽69號埠

當客戶端發送“下載”請求(即讀請求)時,需要向伺服器的69埠發送

伺服器若批准此請求,則使用一個新的、臨時的 埠進行數據傳輸

1、搜索

當伺服器找到需要現在的文件後,會立刻打開文件,把文件中的數據通過TFTP協議發送給客戶端

2、分段

如果文件的總大小較大(比如3M),那麼伺服器分多次發送,每次會從文件中讀取512個位元組的數據發送過來

3、添加序號

因為發送的次數有可能會很多,所以為了讓客戶端對接收到的數據進行排序,所以在伺服器發送那512個位元組數據的時候,會多發2個位元組的數據,用來存放序號,並且放在512個位元組數據的前面,序號是從1開始的

4、添加操作碼

因為需要從伺服器上下載文件時,文件可能不存在,那麼此時伺服器就會發送一個錯誤的信息過來,為了區分服務發送的是文件內容還是錯誤的提示信息,所以又用了2個位元組 來表示這個數據包的功能(稱為操作碼),並且在序號的前面

5、發送確認碼(ACK)

因為udp的數據包不安全,即發送方發送是否成功不能確定,所以TFTP協議中規定,為了讓伺服器知道客戶端已經接收到了剛剛發送的那個數據包,所以當客戶端接收到一個數據包的時候需要向伺服器進行發送確認信息,即發送收到了,這樣的包成為ACK(應答包)

6.發送完畢

為了標記數據已經發送完畢,所以規定,當客戶端接收到的數據小於516(2位元組操作碼+2個位元組的序號+512位元組數據)時,就意味著伺服器發送完畢了

TFTP數據包的格式如下:

 

三、代碼實現

#coding=utf-8

from socket import *
import struct#結構體模塊
import sys

if len(sys.argv) != 2:
    print('-'*30)
    print("tips:")
    print("python xxxx.py 192.168.1.1")
    print('-'*30)
    exit()
else:
    ip = sys.argv[1]#從程式外部獲取參數

# 創建udp套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#構造下載請求數據
cmd_buf = struct.pack("!H8sb5sb",1,"test.jpg",0,"octet",0)

#發送下載文件請求數據到指定伺服器
sendAddr = (ip, 69)
udpSocket.sendto(cmd_buf, sendAddr)

p_num = 0

recvFile = ''

while True:
    recvData,recvAddr = udpSocket.recvfrom(1024)

    recvDataLen = len(recvData)

    # print recvAddr # for test

    # print len(recvData) # for test

    cmdTuple = struct.unpack("!HH", recvData[:4])

    # print cmdTuple # for test

    cmd = cmdTuple[0]
    currentPackNum = cmdTuple[1]        

    if cmd == 3: #是否為數據包

        # 如果是第一次接收到數據,那麼就創建文件
        if currentPackNum == 1:
            recvFile = open("test.jpg", "a")

        # 包編號是否和上次相等
        if p_num+1 == currentPackNum:
            recvFile.write(recvData[4:]);
            p_num +=1
            print '(%d)次接收到的數據'%(p_num)

            ackBuf = struct.pack("!HH",4,p_num)

            udpSocket.sendto(ackBuf, recvAddr)
        # 如果收到的數據小於516則認為出錯
        if recvDataLen<516:
            recvFile.close()
            print '已經成功下載!!!'
            break

    elif cmd == 5: #是否為錯誤應答
        print "error num:%d"%currentPackNum
        break

udpSocket.close()

運行效果:

四、代碼說明

我們寫的是TFTP客戶端的代碼實現,要想實現客戶端的下載功能,首先我們要有一個TFTP伺服器,從網上可以下載Tftp32伺服器軟體

五、struct.pack()和struct.unpack()說明

python中的struct主要是用來處理C結構數據的,讀入時先轉換為Python的字元串類型,然後再轉換為Python的結構化類型,比如元組(tuple)啥的~。一般輸入的渠道來源絡的二進位流。

在轉化過程中,主要用到了一個格式化字元串(format strings),用來規定轉化的方法和格式下麵來談談主要的方法:

1、struct.pack(fmt,v1,v2,.....)

將v1,v2等參數的值進行一層包裝,包裝的方法由fmt指定。被包裝的參數必須嚴格符合fmt。最後返回一個包裝後的字元串

2、struct.unpack(fmt,string)

顧名思義,解包。比如pack打包,然後就可以用unpack解包了。返回一個由解包數據(string)得到的一個元組(tuple), 即使僅有一個數據也會被解中len(string) 必須等於 calcsize(fmt),這裡面涉及到了一個calcsize函數。struct.calcsize(fmt):這個就是用來計算fmt格式所描述的結構的大小。

格式字元串(format string)由一個或多個格式字元(format characters)組成,對於這些格式字元的描述參照Python manual如下:

import struct

buffer = struct.pack("ihb", 1, 2, 3)
print(buffer)
print(repr(buffer))
print(struct.unpack("ihb", buffer))

print("-----------------------------------")

data = [1, 2, 3]
buffer = struct.pack("!ihb", *data)
print(buffer)
print(repr(buffer))
print(struct.unpack("!ihb", buffer))

運行結果為:

b'\x01\x00\x00\x00\x02\x00\x03'
b'\x01\x00\x00\x00\x02\x00\x03'
(1, 2, 3)
-----------------------------------
b'\x00\x00\x00\x01\x00\x02\x03'
b'\x00\x00\x00\x01\x00\x02\x03'
(1, 2, 3)

首先將參數1,2,3打包,打包前1,2,3明顯屬於python數據類型中的integer,pack後就變成了C結構的二進位串,轉成 python的string類型來顯示就是'\x01\x00\x00\x00\x02\x00\x03'。由於本機是小端('little- endian', 故而高位放在低地址段。i 代表C struct中的int類型,故而本機占4位,1則表示為01000000;h 代表C struct中的short類型,占2位,故表示為0200;同理b 代表C struct中的signed char類型,占1位,故而表示為03。

在Format string 的首位,有一個可選字元來決定大端和小端,列表如下:

如果沒有附加,預設為@,即使用本機的字元順序(大端or小端),對於C結構的大小和記憶體中的對齊方式也是與本機相一致的(native),比如有的機器integer為2位而有的機器則為四位;有的機器記憶體對其位四位對齊,有的則是n位對齊(n未知,我也不知道多少)。還有一個標準的選項,被描述為:如果使用標準的,則任何類型都無記憶體對齊。比如剛纔的小程式的後半部分,使用的format string中首位為!即為大端模式標準對齊方式,故而輸出的為'\x00\x00\x00\x01\x00\x02\x03',其中高位自己就被放在記憶體的高地址位了。

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 參考自:https://blog.csdn.net/whl632359961/article/details/73468115 https://www.cnblogs.com/ywl925/archive/2012/11/24/2786105.html 以下是自己做的該功能(發送簡訊、獲取簡訊餘額條 ...
  • 第一種 簡單尋路 地面接觸到的。到達目標點不用跳躍能夠一直走路到達。場景視圖中簡單搭設幾個物體。膠囊體為尋路者,黃球為目標點 紅地板,綠色障礙物。現將地板以及障礙物選中 在檢視面板設置靜態為Navigation Static 如圖2然後菜單欄選擇視窗 Window –Navigation然後選擇Al ...
  • 最近將自己負責的一個核心介面系統從.Net Framework遷移到了.Net Core。 整體過程,從業務層面說一般般吧(整體還好但還是搞的業務有感,沒出嚴重故障)但是技術層面上感覺其實並沒有達到要求,不過預期也是應該不會那麼順利,接下來可能還需要幾個小Fix來處理各種奇奇怪怪的問題。 回顧下遷移 ...
  • Escape: 複製代碼 代碼如下: public static string Escape(string str) { StringBuilder sb = new StringBuilder(); foreach (char c in str) { sb.Append((Char.IsLette ...
  • 項目需求(Winform)可以批量列印某個模板,經過百度和摸索,使用iTextSharp+ZXing.Net+FreeSpire.PDF三個類庫實現了生成pdf、生成條形碼和列印pdf功能。 首先在項目作用使用NuGet獲取這三個類庫的引用。 其次把C:\Windows\Fonts裡面的微軟雅黑字體 ...
  • 近期一直在學習Asp.net Core,微軟的文檔太難看,都是英文翻譯過來的,很不友好,感謝這個博客,從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】,讓我入門了,剛學到這個Swagger時,我就有個需求,因為我之前寫過的系統是分了不同的模塊,模塊裡面再分控制器,不同模塊經常會有相 ...
  • 在用C#調用介面的時候,遇到需要通過調用登錄介面才能調用其他的介面,因為在其他的介面需要在登錄的狀態下保存Cookie值才能有許可權調用, 所以首先需要通過調用登錄介面來保存cookie值,再進行其他介面的調用 1.通過Get方式 但是並不是所有的get請求都需要添加這個heard的內容,有些加了這個 ...
  • 關鍵詞:互聯網、關係型資料庫 強調互聯網,這是因為本文所討論的前提是互聯網應用。與“傳統”應用不同,互聯網中的應用每天面臨的是海量的數據、大量的請求以及對系統可靠性和響應速度有著更高的要求。“傳統”應用,我姑且淺顯地認為是,數據量不大,面對的用戶群範圍相對較小,自然大量的高併發請求場景幾乎不存在。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...