實作的效果如下的Gif所示,就是網路通信Socket模塊實作檔案下載傳輸,
服務端
首先需要獲取本機ip,這里服務端采用多執行緒的方法,就是定義一個函式,然后用threading創建任務,客戶端連接成功,接收客戶端的請求資訊,就是下載的檔案名,所以需要判斷,有輸出檔案位元組數,然后在問用戶是不是要下載,得到資訊就使用 while True: 讀檔案的內容,再一個send,看代碼是不是就是這么回事,
import socket
import os
import threading
# 獲取本機ip
def get_host_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()
return ip
# 處理客戶端請求下載檔案的操作(從主執行緒提出來的代碼)
def deal_client_request(ip_port, service_client_socket):
# 連接成功后,輸出“客戶端連接成功”和客戶端的ip和埠
print("客戶端連接成功", ip_port)
# 接收客戶端的請求資訊【recv】
file_name = service_client_socket.recv(1024)
# 解碼
file_name_data = https://www.cnblogs.com/pythoncxy/p/file_name.decode("utf-8")
# 判斷檔案是否存在
if os.path.exists(file_name_data):
#輸出檔案位元組數
fsize = os.path.getsize(file_name_data)
#轉化為兆單位
fmb = fsize/float(1024*1024)
#要傳輸的檔案資訊
senddata = "https://www.cnblogs.com/pythoncxy/p/檔案名:%s 檔案大小:%.2fMB"%(file_name_data,fmb)
#發送和列印檔案資訊【send】
service_client_socket.send(senddata.encode("utf-8"))
print("請求檔案名:%s 檔案大小:%.2f MB"%(file_name_data,fmb))
#接受客戶是否需要下載【recv】
options = service_client_socket.recv(1024)
if options.decode("utf-8") == "y":
# 打開檔案
with open(file_name_data, "rb") as f:
# 計算總資料包數目
nums = fsize/1024
# 當前傳輸的資料包數目
cnum = 0
while True:
file_data = https://www.cnblogs.com/pythoncxy/p/f.read(1024)
cnum = cnum + 1
#progress = cnum/nums*100
#print("當前已下載:%.2f%%"%progress,end = "\r")
if file_data:
# 只要讀取到資料,就向客戶端進行發送【send】
service_client_socket.send(file_data)
# 資料讀完,退出回圈
else:
print("請求的檔案資料發送完成")
break
else:
print("下載取消!")
else:
print("下載的檔案不存在!")
# 關閉服務當前客戶端的套接字【close】
service_client_socket.close()
if __name__ == '__main__':
# 獲取本機ip
print("TCP檔案傳輸服務器,本機IP:" + get_host_ip())
# 把作業目錄切換到data目錄下
os.chdir("./data")
# 創建套接字【socket】
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 系結埠號【bind】
tcp_server_socket.bind(("", 3356))
# 設定監聽,將主動套接字變為被動套接字【listen】
tcp_server_socket.listen(128)
# 回圈呼叫【accept】,可以支持多個客戶端同時連接,和多個客戶端同時下載檔案
while True:
service_client_socket, ip_port = tcp_server_socket.accept()
# 連接成功后列印套接字號
#print(id(service_client_socket))
# 創建子執行緒
sub_thread = threading.Thread(target=deal_client_request, args=(ip_port, service_client_socket))
# 啟動子執行緒
sub_thread.start()
客戶端
客戶端更簡單,連接服務端,發送下載檔案的請求,定義一個寫入的檔案夾,就是小兒科東西,不寫了,看代碼,
# -*- coding:utf-8 -*-
# 多任務檔案下載器客戶端
import socket
import os
if __name__ == '__main__':
# 創建套接字【socket】
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 和服務端連接【connect】
server_ip = input("輸入服務器IP:")
tcp_client_socket.connect((server_ip, 3356))
# 發送下載檔案的請求
file_name = input("請輸入要下載的檔案名:")
# 編碼
file_name_data = https://www.cnblogs.com/pythoncxy/p/file_name.encode("utf-8")
# 發送檔案下載請求資料【send】
tcp_client_socket.send(file_name_data)
# 接收要下載的檔案資訊【recv】
file_info = tcp_client_socket.recv(1024)
# 檔案資訊解碼
info_decode = file_info.decode("utf-8")
print(info_decode)
#獲取檔案大小
fileszie = float(info_decode.split(':')[2].split('MB')[0])
fileszie2 = fileszie*1024
# 是否下載?輸入y 確認 輸入q 取消
opts = input("是否下載?(y 確認 q 取消)")
if opts == 'q':
print("下載取消!程式退出")
else:
print("正在下載 >>>>>>")
#向服務器確認正在下載【send】
tcp_client_socket.send(b'y')
recvpath = "./receive/"
if not os.path.exists(recvpath):
os.mkdir(recvpath)
# 把資料寫入到檔案里
with open(recvpath + file_name, "wb") as file:
#目前接收到的資料包數目
cnum = 0
while True:
# 回圈接收檔案資料【recv】
file_data = tcp_client_socket.recv(1024)
# 接收到資料
if file_data:
# 寫入資料
file.write(file_data)
cnum = cnum+1
#progress =cnum/fileszie2*100
#print("當前已下載:%.2f%%"%progress,end = "\r")
# 接收完成
else:
print("下載結束!")
break
# 關閉套接字【close】
tcp_client_socket.close()
擴展
如果手機想要下載電腦上的檔案(電腦和手機之間),需要確保電腦和手機連接的網路在同一個路由器下
通過ipconfig查看ip
命令列輸入python -m http.server 8888來搭建局域網
手機訪問192.168.0.101:8888即可下載檔案
本文已收錄 GitHub,傳送門~ ,里面更有大廠面試完整考點,歡迎 Star,
作者:劉潤森
鏈接:https://juejin.im/post/6893692196978065421
來源:掘金
著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/210997.html
標籤:Python
上一篇:第一個Django專案
