熱線電話:13121318867

登錄
首頁精彩閱讀python利用socketserver實現并發套接字功能
python利用socketserver實現并發套接字功能
2018-08-05
收藏

python利用socketserver實現并發套接字功能

本文實現利用python的socketserver這個強大的模塊實現套接字的并發,具體內容如下

目錄結構如下:

測試文件請放在server_file文件夾里面

server.py

#!/usr/bin/env python
# -*- coding: gbk -*-
# @Version : Python 3.5.2
# @Time : 2018/1/24 10:29
# @Author : Ncp
# @File : server.py
# @Software: PyCharm
 
import json
import time
import hashlib
import struct
import os
from socketserver import *
 
FILE_PATH = os.path.dirname(os.path.abspath(__file__))+'\\server_file'
 
class MYserver(BaseRequestHandler): # 設置一個類,基礎BaseRequestHandler這個類
 def handle(self):     # 這個方法下添加通信功能(和上面創建類一樣,這是socketserver的固定模式)
  print(self.client_address)
  '''
  :functions: 使用socketserver的并發套接字,提供客戶端下載文件,并對文件進行MD5加密
  '''
  while True:
   try:
    data = self.request.recv(1024)
    data_recv = data.decode('gbk').split()
    if not os.path.exists(FILE_PATH+r'\%s' %data_recv[1]):
     self.request.send('file is not found'.encode('gbk'))
     continue
    else:
     data = self.request.send('1'.encode('gbk')) # 這里發現小問題,不回復一個信息的話,發送給客戶端的包頭居然成了沒有封裝
     FILE_SIZE = os.path.getsize(FILE_PATH+r'\%s' %data_recv[1])
     with open(FILE_PATH+r'\%s' %data_recv[1],'rb')as f:
      hash_file = f.read()
     m = hashlib.md5()
     m.update(hash_file)
     m_hex = m.hexdigest()
     file_header = {'filename':data_recv[1],
         'filesize':FILE_SIZE,
         'md5':m_hex,
         'time':time.strftime('%Y-%m-%d-%X',time.localtime())
         }
     # 包頭信息序列化
     file_header_dump = json.dumps(file_header)
     # 編譯成2進制
     file_header_bytes = file_header_dump.encode('gbk')
     # 封裝報頭
     file_header_struct = struct.pack('i',len(file_header_bytes))
     # 發送報頭
     self.request.send(file_header_struct)
     # 發送報文內容
     self.request.send(file_header_bytes)
     # 發送文件數據
     send_size = 0
     with open(FILE_PATH+r'\%s' %data_recv[1] , 'rb')as f:
      for i in f:
       self.request.send(i)
       send_size += len(i) # 這里后續可以拓展一個進度或者網速顯示功能
   except Exception:
    self.request.close()
 
 
if __name__ == '__main__':
 server = ThreadingTCPServer(('127.0.0.1',8080),MYserver) # windows下只能開啟多線程
 server.serve_forever()

client.py    
#!/usr/bin/env python
# -*- coding: gbk -*-
# @Version : Python 3.5.2
# @Time : 2018/1/24 10:29
# @Author : Ncp
# @File : client.py
# @Software: PyCharm
 
from socket import *
import os,sys
import hashlib
import struct
import math
import json
 
FILE_PATH = os.path.dirname(os.path.abspath(__file__))+'\\client_file'
 
 
# 顯示下載進度條功能,可以拓展為顯示下載速度(提示,因為每次傳輸4096個字節,那么下載網速為KB/S,1KB個字節=1024B(字節),那么1s傳輸了多少個字節呢?)
def progress(recvd, total):
 fraction = '{:.0%}'.format(recvd / total)
 sys.stdout.write('\r[%-30s] %s' % ('#' * int(math.floor(recvd * 30 / total)), fraction))
 sys.stdout.flush()
 if recvd == total:
  sys.stdout.write('\n')
 
 
# 主函數
def run(ip,addr):
 client = socket(AF_INET,SOCK_STREAM)
 client.connect((ip,addr))
 while True:
  user_input = input('>>').strip()
  cmd = user_input.split()
  if len(cmd) != 2:
   print('input format is error please use:get xx')
   continue
  if cmd[0] == 'get':
   client.send(user_input.encode('gbk'))
   data = client.recv(1024)
   data_recv = data.decode('gbk')
   if data_recv == 'file is not found':
    print(data_recv)
    continue
  else:
   print('commands is not found')
   continue
  # 收包頭,然后一系列處理
  header = client.recv(4)
  if not header:break
  header_json_len = struct.unpack('i', header)[0]
  header_json_bytes = client.recv(header_json_len)
  header_josn = header_json_bytes.decode('gbk')
  header_dic = json.loads(header_josn)
  # 去除包頭內容進行下載
  print(header_dic)
  data_len = header_dic['filesize']
  data_file = header_dic['filename']
  data_md5 = header_dic['md5']
  recv_size = 0
  with open(FILE_PATH+r'\%s' %data_file,'wb')as fw:
   while recv_size < data_len:
    recv_data = client.recv(4096)
    recv_size += len(recv_data)
    fw.write(recv_data)
    progress(recv_size,data_len)
   print('Download completion, start validation')
  # 收到文件后,讀取文件進行加密,看是否與服務端下載的文件一致!
  with open(FILE_PATH+r'\%s' %data_file,'rb')as fr:
   data_total = fr.read()
 
  m = hashlib.md5()
  m.update(data_total)
  m_hex = m.hexdigest()
 
  if m_hex == data_md5:
   print('文件驗證通過')
  else:
   print('文件損壞,刪除文件')
   os.remove(FILE_PATH+r'\%s' %data_file)
 
 
if __name__ == '__main__':
 run('127.0.0.1',8080)

自己可以設置一個多用戶登錄,然后測試,用戶下載同一個文件,分別存入每個用戶自己的家目錄下面,效果更好。
當然現在也能測試,開啟兩個客戶端同時下載文件。

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢