编写cs架构的软件,实现客户端可以下载服务端的文件,如图片、视频、文本等-练习

TCP服务端

"""
编写cs架构的软件,实现客户端可以下载服务端的文件,如图片、视频、文本等
"""
import socketserver
import os
import json
import struct


def base_path(*paths):
    return os.path.normpath(os.path.join(__file__, '..', 'db', *paths))


class MyRequestHandler(socketserver.BaseRequestHandler):
    DB_PATH = base_path()

    def header(self, request=False, warn=None, info=None, file_name=None, file_size=None):
        # 定制头部
        dic = {
            'request': request,
            'file_name': file_name,
            'file_size': file_size,
            'warn': warn,
            'info': info,
        }
        dic_json_bytes = json.dumps(dic).encode('utf-8')
        header_bytes = struct.pack('i', len(dic_json_bytes))
        self.request.send(header_bytes)
        self.request.send(dic_json_bytes)

    def verify_path(self, path_json):
        # 逻辑判断
        current_path = base_path(*path_json.split('/'))
        print('current_path:', current_path)
        if not os.path.isfile(current_path):
            return
        if len(self.DB_PATH) >= len(current_path):
            return
        return current_path

    def send(self, current_path):
        file_size = os.path.getsize(current_path)
        file_name = os.path.basename(current_path)
        info = '执行命令成功! 正在为您下载文件....'
        self.header(True, file_size=file_size, file_name=file_name, info=info)
        with open(current_path, 'rb') as f:
            for line in f:
                # 发送数据
                self.request.send(line)

    def handle(self):
        print('客户端访问:', self.client_address)
        while True:
            try:
                path_json = self.request.recv(1024).decode('utf-8')
                print('path_json:', path_json)
                if not path_json:
                    break
                # 1. 定制头部

                # 2. 逻辑判断
                current_path = self.verify_path(path_json)

                if not current_path:
                    self.header(warn='对不起, 您的文件路径不存在!')
                    continue

                # 3. 发送数据
                self.send(current_path)
            except ConnectionResetError:
                break
            except Exception:
                break
        print("客户端断开连接:", self.client_address)
        self.request.close()


s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyRequestHandler)
s.serve_forever()

TCP客户端

"""
编写cs架构的软件,实现客户端可以下载服务端的文件,如图片、视频、文本等
"""
import os
import json
from socket import *

client = socket(AF_INET, SOCK_STREAM)
client.connect(("127.0.0.1", 8080))

def progress(percent, symbol='#', width=50):
    if percent > 1:
        percent = 1
    show_progress = ("[%%-%ds]" % width) % (int(percent * width) * symbol)
    print("\r%s %.2f%%" % (show_progress, percent * 100), end='')

while True:
    cmd = input("[下载: get /路径/路径../文件]请输入命令>>: ").strip()
    if not cmd:
        continue

    cmd_list = cmd.split()
    if len(cmd_list) != 2:
        print('对不起, 输入错误!')
        continue

    cmd, path = cmd_list
    if cmd != 'get':
        print("对不起, 下载文件请执行命令get")
        continue
    # 1. 发送命令
    client.send(path.encode('utf-8'))

    # 2. 解包
    import struct

    header_bytes = client.recv(4)
    json_dic_bytes_length = struct.unpack('i', header_bytes)[0]
    json_dic_bytes = client.recv(json_dic_bytes_length)
    dic = json.loads(json_dic_bytes.decode('utf-8'))
    print(dic)

    # 3. 逻辑判断
    request = dic['request']
    if not request:  # 失败
        print(dic['warn'])
        continue
    info, file_size, file_name = dic['info'], dic['file_size'], dic['file_name']

    # 接收数据
    print(info)
    print("start recv........")
    with open(file_name, 'wb') as f:
        recv_size = 0
        while recv_size < file_size:
            data_bytes = client.recv(1024)
            f.write(data_bytes)
            recv_size += len(data_bytes)
            percent = recv_size / file_size
            progress(percent)
    print("\nend recv........")

client.close()

posted @ 2020-04-22 02:47  给你加马桶唱疏通  阅读(540)  评论(0编辑  收藏  举报