一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - python利用socketserver實現并發套接字功能

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

2021-01-09 00:28成長的網工 Python

這篇文章主要為大家詳細介紹了python利用socketserver實現并發套接字功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

目錄結構如下:

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

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

server.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/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)

自己可以設置一個多用戶登錄,然后測試,用戶下載同一個文件,分別存入每個用戶自己的家目錄下面,效果更好。

當然現在也能測試,開啟兩個客戶端同時下載文件。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.cnblogs.com/encp/archive/2018/01/26/8358432.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲天堂三区 | 小小水蜜桃视频高清在线播放 | 久久久亚洲国产精品主播 | gayrb漫画免费入口 | 动漫美女被吸乳 | 国产无套在线播放 | 91在线播| 无颜之月全集免费观看 | 国产一卡2卡3卡四卡精品网站 | 欧美视频一区二区三区在线观看 | 欧美成人aletta ocean | 欧美成人第一页 | 午夜性爽视频男人的天堂在线 | 美女张开大腿让男人桶 | 免费av在线视频 | 全黄一级裸片视频免费 | 日本69av| 成人综合婷婷国产精品久久免费 | 免费看打屁股视频的软件 | 亚洲国产精品综合福利专区 | 窝窝午夜精品一区二区 | 热热99 | 免费网站视频 | 亚洲男人精品 | 太深了 太粗h1v1 | adult video在线观看 | 干美女视频 | 按摩师他揉我奶好爽捏我奶 | 欧美人成绝费网站色www吃脚 | 91在线视频导航 | 91精品免费观看老司机 | 久久丫线这里只精品 | 午夜影院免费看 | 任我行视频在线观看国语 | 亚洲国产精品日本无码网站 | 国产精品免费久久久久影院 | 国产成人啪精品午夜在线播放 | 毛片大全免费看 | 日韩在线1 | 日韩高清在线高清免费 | 亚洲成在人线视频 |