server端

import os
import json
import struct
import socketserver

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            file_info_length_pack = self.request.recv(4)  #接收报头定长4个字节
            file_info_length = struct.unpack('i',file_info_length_pack)[0]  #得到传输的字典字节串长度

            file_info_json = self.request.recv(file_info_length).decode('utf-8')  #接收字典字节串,并解码
            file_info = json.loads(file_info_json)  #反序列化字典字符串得到字典

            operate = file_info['operate']   #得到传输过来字典里面的每一项内容
            filename = file_info['filename']
            filesize = file_info['filesize']

            if operate == 'upload':  #上传进行一下操作
                with open(filename,'wb') as f1:
                    filesize_sum = 0  #定义一个变量记录已经接收的长度
                    while filesize_sum < filesize:
                        data = self.request.recv(1024)
                        filesize_sum += len(data)
                        f1.write(data)   #接收一次写一次
                print('接收成功')

            else:  #下载进行以下操作
                with open(filename,'rb') as f2:
                    for line in f2:   #读取文件的每一行,然后把每一行传给客户端
                        self.request.send(line)
                print('传输成功')





server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Myserver)
server.serve_forever()
View Code

 

client端

 

import os
import json
import struct
import socket

client = socket.socket()  #建立连接
client.connect(('127.0.0.1',8080))

while True:
    choice_list = ['upload','download']
    for num,choice in enumerate(choice_list,1):
        print(num,choice)    #打印目录
    choice_one = int(input('请输入要选择的序号:').strip())
    filename = input('请输入要操作的文件:').strip()
    filesize = os.path.getsize(filename)  #得到文件的大小
    file_info = {
        'operate': choice_list[choice_one - 1],
        'filename': filename,
        'filesize': filesize
    }       #把要传输的文件相关内容定义为一个字典,方便传输
    file_info_json = json.dumps(file_info).encode('utf-8')  #序列化并编码成字典字节串
    ret = struct.pack('i', len(file_info_json))   #将序列化的字典字节串打包成定长
    client.send(ret)  #传输长度
    client.send(file_info_json)  #传输字典字节串

    if choice_one == 1:  #选择上传的话进行一下操作
        with open(filename,'rb') as f1:
            for line in f1:  #读取每一行,把每一行传给服务器
                client.send(line)
        print('上传成功!')

    elif choice_one == 2:  #选择下载的话进行以下操作
        with open(filename,'wb') as f2:
            filesize_sum = 0  #定义一个变量记录已经接收到的长度
            while filesize_sum < filesize:
                data = client.recv(1024)
                filesize_sum += len(data)
                f2.write(data)  #接收一次写入一次

        print('下载成功!')
View Code

 

 

此版本代码可以同时打开多个客户端进行传输,利用了黏包的问题,解决了多次传输接收的问题,提高了效率