日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

[转载] Python中TFTP的理解

發(fā)布時(shí)間:2025/3/11 python 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] Python中TFTP的理解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考鏈接: Python中的打包pack和拆包unpack參數(shù)

Num01–>TFTP協(xié)議介紹?

?

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

?是TCP/IP協(xié)議族中的一個(gè)用來在客戶端與服務(wù)器之間進(jìn)行簡單文件傳輸?shù)膮f(xié)議?

?特點(diǎn):?

?1,簡單? 2,占用資源小? 3,適合傳遞小文件? 4,適合在局域網(wǎng)進(jìn)行傳遞? 5,端口號為69? 6,基于UDP實(shí)現(xiàn)?

?

Num02–>TFTP下載過程?

?

?TFTP服務(wù)器默認(rèn)監(jiān)聽69號端口?

?當(dāng)客戶端發(fā)送“下載”請求(即讀請求)時(shí),需要向服務(wù)器的69端口發(fā)送?

?服務(wù)器若批準(zhǔn)此請求,則使用一個(gè)新的、臨時(shí)的 端口進(jìn)行數(shù)據(jù)傳輸?

?

?

?

?當(dāng)服務(wù)器找到需要現(xiàn)在的文件后,會立刻打開文件,把文件中的數(shù)據(jù)通過TFTP協(xié)議發(fā)送給客戶端?

?如果文件的總大小較大(比如3M),那么服務(wù)器分多次發(fā)送,每次會從文件中讀取512個(gè)字節(jié)的數(shù)據(jù)發(fā)送過來?

?因?yàn)榘l(fā)送的次數(shù)有可能會很多,所以為了讓客戶端對接收到的數(shù)據(jù)進(jìn)行排序,所以在服務(wù)器發(fā)送那512個(gè)字節(jié)數(shù)據(jù)的時(shí)候,會多發(fā)2個(gè)字節(jié)的數(shù)據(jù),用來存放序號,并且放在512個(gè)字節(jié)數(shù)據(jù)的前面,序號是從1開始的?

?因?yàn)樾枰獜姆?wù)器上下載文件時(shí),文件可能不存在,那么此時(shí)服務(wù)器就會發(fā)送一個(gè)錯(cuò)誤的信息過來,為了區(qū)分服務(wù)發(fā)送的是文件內(nèi)容還是錯(cuò)誤的提示信息,所以又用了2個(gè)字節(jié) 來表示這個(gè)數(shù)據(jù)包的功能(稱為操作碼),并且在序號的前面?

?

操作碼? ? ?功能

?1? ? ? 讀請求,即下載

?2? ? ? 寫請求,即上傳

?3? ? ? 表示數(shù)據(jù)包,即DATA

?4? ? ? 確認(rèn)碼,即ACK

?5? ? ? 錯(cuò)誤?

?

?因?yàn)閡dp的數(shù)據(jù)包不安全,即發(fā)送方發(fā)送是否成功不能確定,所以TFTP協(xié)議中規(guī)定,為了讓服務(wù)器知道客戶端已經(jīng)接收到了剛剛發(fā)送的那個(gè)數(shù)據(jù)包,所以當(dāng)客戶端接收到一個(gè)數(shù)據(jù)包的時(shí)候需要向服務(wù)器進(jìn)行發(fā)送確認(rèn)信息,即發(fā)送收到了,這樣的包成為ACK(應(yīng)答包)?

?為了標(biāo)記數(shù)據(jù)已經(jīng)發(fā)送完畢,所以規(guī)定,當(dāng)客戶端接收到的數(shù)據(jù)小于516(2字節(jié)操作碼+2個(gè)字節(jié)的序號+512字節(jié)數(shù)據(jù))時(shí),就意味著服務(wù)器發(fā)送完畢了?

?

Num03–>TFTP數(shù)據(jù)包的格式?

?

Num04–>TFTP客戶端案例編寫?

#! /usr/bin/env python3

# -*- coding:utf-8 -*-?

?

from socket import *

import struct #為了實(shí)現(xiàn)打包struct.pack()和拆包struct.unpack()數(shù)據(jù)

import sys

?

# python3 05-xx.py 192.168.105.125 bb.jpg

def main():

?

? ? if len(sys.argv) < 3:

? ? ? ? sys.exit('usage : python3? %s ip filename' % sys.argv[0])

?

? ? #server_ip = '192.168.105.125'

? ? #file_name = 'bb.jpg'

?

? ? server_ip = sys.argv[1]

? ? file_name = sys.argv[2]

?

? ? udp_socket = socket(AF_INET, SOCK_DGRAM)

? ? server_addr = (server_ip,69)

?

? ? #? 打包數(shù)據(jù)

? ? # !表示網(wǎng)絡(luò)字節(jié)序,H表示2bytes無符號整數(shù),

? ? #? 5s表示長度為5字符串

? ? #? B表示1byte的無符號整數(shù)

? ? fmt = '!H%dsB5sB' % len(file_name)

? ? send_data = struct.pack(fmt,1,file_name.encode() ,0,b'octet',0)

? ? #send_data = struct.pack(fmt,1,file_name ,0,b'octet',0)

?

? ? udp_socket.sendto(send_data,server_addr)

?

? ? f =? None # 文件對象

? ? #上一次blockNum

? ? lastBlockNum = 0

?

? ? # 循環(huán)接收和應(yīng)答

? ? while True:

? ? ? ? recv_data,peer_addr = udp_socket.recvfrom(1024)

? ? ? ? # 拆包數(shù)據(jù)

? ? ? ? opcode,blockNum = struct.unpack('!HH',recv_data[:4])

?

? ? ? ? if opcode == 3: # 表示數(shù)據(jù)包

? ? ? ? ? ? # 寫入文件

? ? ? ? ? ? # 1打開文件

? ? ? ? ? ? # 第一次收到服務(wù)器發(fā)送數(shù)據(jù)包

? ? ? ? ? ? if blockNum == 1:?

? ? ? ? ? ? ? ? f = open(file_name,'wb')

?

? ? ? ? ? ? # 拆出數(shù)據(jù)

? ? ? ? ? ? data_fmt = '!%ds' % (len(recv_data) - 4)

? ? ? ? ? ? data_content = struct.unpack(data_fmt, recv_data[4:])

?

? ? ? ? ? ? # 寫入文件之前判斷寫過沒有

? ? ? ? ? ? # if 這一次blockNum == 上一次blockNum + 1

? ? ? ? ? ? if lastBlockNum + 1 == blockNum:

? ? ? ? ? ? ? ? #print(data_content[0])

? ? ? ? ? ? ? ? f.write(data_content[0]) # 拆出來是元組,bytes對象,write時(shí)候需要str字符串

?

? ? ? ? ? ? # 打包應(yīng)答數(shù)據(jù)

? ? ? ? ? ? ack_data = struct.pack('!HH',4,blockNum)

? ? ? ? ? ? udp_socket.sendto(ack_data,peer_addr) # 不能再給server_addr,因?yàn)槎丝谔栕兞?/p>

?

? ? ? ? ? ? # 當(dāng)應(yīng)答完畢,更新lastBlockNum

? ? ? ? ? ? lastBlockNum = blockNum

?

? ? ? ? ? ? # 如果數(shù)據(jù)長度小于 2 + 2 + 512 傳輸結(jié)束

? ? ? ? ? ? if len(recv_data) < 516:

? ? ? ? ? ? ? ? print('over')

? ? ? ? ? ? ? ? f.close()

? ? ? ? ? ? ? ? break

? ? ? ? elif opcode == 5:# 出錯(cuò)

? ? ? ? ? ? err_num = blockNum

? ? ? ? ? ? # 拆出錯(cuò)誤信息

? ? ? ? ? ? fmt = "!%ds" % (len(recv_data) - 5)

? ? ? ? ? ? err_msg = struct.unpack(fmt,recv_data[4:-1])

? ? ? ? ? ? print('出錯(cuò)信息:%s' % err_msg)

? ? ? ? ? ? break

?

if __name__ == "__main__":

? ? main()

總結(jié)

以上是生活随笔為你收集整理的[转载] Python中TFTP的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。