1. 程式人生 > 程式設計 >python中的socket實現ftp客戶端和伺服器收發檔案及md5加密檔案

python中的socket實現ftp客戶端和伺服器收發檔案及md5加密檔案

客戶端向伺服器傳送一個請求,請求內容是一個檔名,伺服器在查詢自己這邊有沒有這個檔案,如果有的話就傳送給客戶端

1、客戶端

  1. 生成socket物件
  2. 建立連線
  3. 輸入想要接收的檔案
  4. 將輸入的檔名傳送給伺服器
  5. 接收伺服器發回的關於即將要傳送來的檔案的大小
  6. 傳送一條資訊給伺服器告訴它準備好接收了
  7. 接收檔案資料
  8. 列印全部接收的提示資訊

client具體實現的程式碼如下:

# Author: Mr.Xue
# 2019.10.29
# socket_ftp_client.py

import socket
import hashlib

client = socket.socket() # 生成socket連線物件
client.connect(('localhost',6961)) # 建立連線

while True:
 cmd = input(">>").strip() # 輸入想要接收的檔案
 if len(cmd) == 0: continue # 輸入為空,重新再輸
 if cmd.startswith('get'): # 判斷指令是否以get開頭
 client.send(cmd.encode("utf-8")) # 傳送
 server_response = client.recv(1024) #接收即將傳送來的檔案的大小
 print("server response:",server_response) # 列印檔案的大小
 client.send(b'ready to recv file...') # 傳送訊息告訴服務已經準備好接收了
 file_total_size = int(server_response.decode()) # 記錄檔案的總大小
 received_size = 0 # 記錄已經接收了的檔案的大小
 filename = cmd.split()[1] # 取出輸入的檔名
 f = open(filename + '.new','wb') # 新建一個本地檔案來儲存接收的資料
 m = hashlib.md5() # md5加密
 while received_size < file_total_size:
  data = client.recv(1024) # 接收資料,一次最大接收1024bytes
  received_size += len(data) # 記錄已接收的資料大小
  m.update(data) # 用md5加密
  f.write(data) # 寫入檔案
 else:
  new_file_md5 = m.hexdigest() # 16進位制顯示加密檔案
  print("file recv done",received_size,file_total_size)
  f.close()
  server_md5 = client.recv(1024) # 接收伺服器端以md5加密的這個接收檔案的加密檔案,拿來和接收之後的加密檔案做比較
  print("md5",new_file_md5,server_md5)
client.close() 

client端比較難的一點和上篇一樣,還是如何判斷伺服器端要傳送的資料,客戶端是否完全都接收過來了,實現邏輯在上面程式碼中,也可參考前一篇socket(二);在客戶端這一次多了一個新的知識點,用md5來加密接收到的檔案,先生成md5例項物件,再呼叫update()來加密檔案,最後和伺服器端的加密檔案進行比較,看看是不是一樣的。

2、伺服器

  1. 生成socket連線物件
  2. 繫結要監聽埠
  3. 監聽
  4. 等待客戶端的連線
  5. 接收客戶端發來的檔名
  6. 查詢這個檔案是否存在
  7. 如果存在,開啟檔案計算大小,傳送給客戶端
  8. 等待客戶端確認
  9. 傳送檔案具體內容給客戶端

server具體實現程式碼如下:

# Author: Mr.Xue
# 2019.10.29
# socket_ftp_server.py

import socket,os,hashlib

server = socket.socket() #生成socket物件
server.bind(('localhost',6961)) # 繫結ip和埠
server.listen() #監聽
while True:
 conn,addr = server.accept() # 等待客戶端連線
 while True:
 print("等待接收檔名...")
 data = conn.recv(1024) # 接收客戶端發來的資訊
 if not data: #判斷客戶端是否斷連
  print('lost a link...')
  break
 cmd,filename = data.decode().split() # 分割接收到的訊息,提取出檔名
 if os.path.isfile(filename): # 判斷檔案是否存在
  f = open(filename,'rb') # 開啟檔案
  m = hashlib.md5() # md5加密物件
  file_size = os.stat(filename).st_size # 計算檔案大小
  conn.send(str(file_size).encode("utf-8")) # send file size
  conn.recv(1024) # wait the ack 預防粘包
  for line in f:
  m.update(line) # 加密
  conn.send(line) # 傳送
  print("file md5:",m.hexdigest()) # 以16進位制列印加密後的檔案
  f.close() # 關閉檔案
  conn.send(m.hexdigest().encode("utf-8")) # 以16進位制傳送加密後的檔案
 print('send done')
socket.close()

伺服器的具體實現邏輯和前一篇大體上沒什麼區別,主要處理細節誒變成了查詢檔案處理檔案和加密檔案

3、測試效果

啟動伺服器

xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py

啟動客戶端

client

xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_client.py
>>

server

xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py
等待接收檔名...

客戶端傳送想要接收的檔名

client

xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_client.py
>>get a.txt
server response: b'90'
file recv done 90 90
md5 2232897a127542c1d0715e66e7ca57cc b'2232897a127542c1d0715e66e7ca57cc'
>>

server

xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py
等待接收檔名...
file md5: 2232897a127542c1d0715e66e7ca57cc
send done
等待接收檔名...

上面的伺服器端在傳送完資料之後,接著又傳送了md5的加密檔案,可能會發生粘包的情況,所以上面還存在改進的地方,將預防粘包的程式碼加進去就比較完美了。

總結

到此這篇關於python中的socket實現ftp客戶端和伺服器收發檔案及md5加密檔案的文章就介紹到這了,更多相關python socket 實現ftp 收發檔案md5加密檔案內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!