Python完成檔案傳輸

2021-09-10 07:52:09 字數 3526 閱讀 9564

一、什麼是tftp?

tftp(trivial file transfer protocol,簡單檔案傳輸協議)是tcp/ip協議族中的乙個用來在客戶機與伺服器之間進行簡單檔案傳輸的協議,提供不複雜、開銷不大的檔案傳輸服務。埠號為69。

二、tftp伺服器、客戶端傳輸原理

1、首先,客戶端傳送乙個讀寫請求的資料報給伺服器

該包的格式為:操作碼(2位元組)+檔名(n位元組)+ 0(1位元組)+ 模式(固定,為octet)+0(1位元組)

2、伺服器收到了這個包後,會返回傳送乙個包

該包格式分兩種,一種是伺服器有這個請求的檔案,所以發了所請求的資料報

該包格式為:操作碼(2位元組) + 塊編號(2位元組) + 資料(512位元組)

另一種是,伺服器告訴客戶端並沒有這個檔案或者是其它的錯誤

該包格式為:操作碼(2位元組) + 差錯碼(2位元組) + 差錯資訊(n位元組) + 0(1位元組)

3、客戶端收到了伺服器傳送的資料報,傳送乙個ack包給伺服器(意思就是告訴伺服器,我收到你發給我的這個包了,因為是udp協議,所以有丟包的可能,以此來確認資料報)

4、當伺服器傳送給客戶端的包小於516位元組時,完成傳輸

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

四、各個模組的實現

關於pack與unpack

pack 負責將不同的變數打包在一起,成為乙個位元組字串。

unpack 將位元組字串解包成為變數。

'''h對應1,指1站兩個位元組,8s對應「test.jpg」,b對應0站乙個位元組,5s對應「octet」,b對應0站乙個位元組'''

sendaddr=(ip,69)

udpsocket=socket.socket(af_inet,sock_dgram)

udpsocket.sendto(cmd_buf,sendaddr)

send_request()

五、tftp客戶端程式原始碼演示:test.jpg

#用於存放訪問伺服器的ip位址

ip=""

# 建立udp套接字

udpsocket = socket(af_inet, sock_dgram)

#用於確定包的順序

p_num = 0

#建立檔案

recvfile = ''

def print_menu():

'''解釋用法'''

print("未輸入ip位址!")

def start_download():

while true:

global recvfile

global p_num

#用兩個變數接收返回 資料、(源ip位址,埠)

recvdata,recvaddr = udpsocket.recvfrom(1024)

#記錄資料報的長度

recvdatalen = len(recvdata)

#解包,獲取伺服器返回資料報前四位位元組。前兩位位元組代表操作碼

'''2寫請求,即上傳

3表示資料報,即data

4確認碼,即ack

5錯誤'''

cmdtuple = struct.unpack("!hh", recvdata[:4])

#獲取操作碼

cmd = cmdtuple[0]

#獲取塊編號,用於區分資料報的排列順序

currentpacknum = cmdtuple[1]

if cmd == 3: #是否為資料報

# 如果是第一次接收到資料,那麼就建立檔案

if currentpacknum == 1:

recvfile = open("test.jpg", "wb") #wb以二進位制形式開啟

if p_num+1 == currentpacknum:

recvfile.write(recvdata[4:])

p_num+=1

print("(%d)次接收到的資料"%(p_num))

#構建ack包,傳送ack包,告訴伺服器,我收到這個包了

ackbuf = struct.pack("!hh",4,p_num)

udpsocket.sendto(ackbuf, recvaddr)

# 為了標記資料已經傳送完畢,所以規定,當客戶端接收到的資料小於516

#(2位元組操作碼+2個位元組的序號+512位元組資料)時,就意味著伺服器傳送完畢了

if recvdatalen<516:

recvfile.close()

break

elif cmd == 5: #是否為錯誤應答,即表達伺服器沒有這個檔案或其他錯誤

print("error num:%d"%currentpacknum)

break

udpsocket.close()

def main():

global ip

#1.列印介面

print_menu()

#2.傳送請求

send_request()

start_download()

if __name__ == '__main__':

main()

利用 TCP 完成檔案傳輸的設計

輸入檔案路徑,利用 tcp 實現客戶檔案向伺服器的傳輸,並實現對 tcp 的基本封裝 1 建立 socket 2 確定伺服器 scokaddr in 結構體 3 點分十進位制 ip 轉換 4 使用 bind 繫結套接字 5 使用 listen 監聽 6 使用 accept 接受連線請求 7 acce...

Python檔案傳輸

encode是編碼 例如 name.encode gb2312 表示將字串name以gb2312編碼。decode是解碼 例如 name.decode gb2312 表示將字串name以gb2312解碼。按行讀取txt裡的檔名,把檔案移到指定的路徑裡。coding utf 8 import thre...

python實現檔案傳輸

我程式設計的時候,開了兩個python的shell,乙個做server,乙個做client 然後就直接在命令提示符下一行一行的編,感覺自己是在使用一套高階命令列,而不是在程式設計。server端 import socket sersock socket.socket socket.af inet,s...