xiao-apple36

传输文件简单版

server端:

import socket
import struct
import json
import os

share_dir = r\'C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\server\share\'
IP_PORT = (\'127.0.0.1\', 8999)

def bytes2human(n):
    symbols = (\'K\', \'M\', \'G\', \'T\', \'P\', \'E\')
    prefix = {}
    for i, s in enumerate(symbols):
        # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
        # 10位就表示1024 即1 << 10=1024 就是2的n次方
        prefix[s] = 1 << (i + 1) * 10
    for s in reversed(symbols):
        if n >= prefix[s]:
            value = float(n) / prefix[s]
            return \'%.2f%s\' % (value, s)
    return "%sB" % n

def get(conn,file_name):
    # 3、以读的方式打开文件,读取文件内容发送给客户端
    # 第一步:制作固定长度的报头
    print(\'get\')
    try:
        header_dict = {
            \'file_name\': file_name,
            \'md5\': \'xxx\',
            \'file_size\': os.path.getsize(os.path.join(share_dir, file_name))

        }

        header_json = json.dumps(header_dict, ensure_ascii=\'False\', indent=2)
        header_bytes = header_json.encode(\'utf-8\')
        # 第二步:先发送报头的长度
        conn.send(struct.pack(\'i\', len(header_bytes)))

        # 第三步:再发报头
        conn.send(header_bytes)

        # 第四步:再发送真实的数据
        with open(os.path.join(share_dir, file_name), \'rb\') as f:
            for line in f:
                conn.send(line)

    except Exception as e:
        print(e)


def put(conn, file_name):
    """
     接收客户端上传文件
    :param conn:
    :param file_name:
    :return:
    """
    # 2、以写的方式打开一个新文件,接收客户端发来的文件的内容写入服务端新文件
    # 第一步:先收报头的长度
    header_len = conn.recv(4)
    header_size = struct.unpack(\'i\', header_len)[0]

    # 第二步:再收报头
    header_json = conn.recv(header_size).decode(\'utf-8\')

    # 第三步:从报头中解析出对真实数据的描述信息
    header_dict = json.loads(header_json)
    file_size = header_dict[\'file_size\']
    file_name = header_dict[\'file_name\']

    print(os.path.join(share_dir, file_name))
    # 第四步:接收真实的数据,写入文件
    with open(os.path.join(share_dir, file_name), \'wb\') as f:
        recv_size = 0
        while recv_size < file_size:
            line = conn.recv(1024)
            f.write(line)
            recv_size += len(line)
            print(\'总大小:%s   已上传大小:%s\' % (bytes2human(file_size), bytes2human(recv_size)))


def run():
    server = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
    server.bind(IP_PORT)

    server.listen(5)
    print(\'starting...\')

    while True:

        conn, addr = server.accept()
        print(addr)

        while True:
            try:
                # 1 收命令
                res = conn.recv(1024)  # b\' get a.txt\'
                if not res:break
                # 2、解析命令,提取相应命令参数
                cmds = res.decode(\'utf-8\').split()  # [get, a.txt]
                if cmds[0] == \'get\':
                    get(conn, cmds[1])  # 下载文件
                    # file_name = cmds[1]
                elif cmds[0] == \'put\':
                    put(conn, cmds[1])  # 上传文件
            except ConnectionResetError: #适用于windows操作系统
                break
        conn.close()

    server.close()


if __name__ == \'__main__\':
    run()

  

 

client端

  

#!/usr/bin/env python3 
# -*- coding: utf-8 -*-


import socket
import struct
import json
import os

share_dir = r\'C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\client\download\'
IP_PORT = (\'127.0.0.1\', 8999)


def bytes2human(n):
    symbols = (\'K\', \'M\', \'G\', \'T\', \'P\', \'E\')
    prefix = {}
    for i, s in enumerate(symbols):
        # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
        # 10位就表示1024 即1 << 10=1024 就是2的n次方
        prefix[s] = 1 << (i + 1) * 10
    for s in reversed(symbols):
        if n >= prefix[s]:
            value = float(n) / prefix[s]
            return \'%.2f%s\' % (value, s)
    return "%sB" % n


def get(client, file_name):
    # 2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户的新文件
    # 第一步:先收报头的长度
    header_len = client.recv(4)
    header_size = struct.unpack(\'i\', header_len)[0]

    # 第二步:再收报头
    header_json = client.recv(header_size).decode(\'utf-8\')

    # 第三步:从报头中解析出对真实数据的描述信息
    header_dict = json.loads(header_json)
    file_size = header_dict[\'file_size\']
    file_name = header_dict[\'file_name\']

    print(os.path.join(share_dir, file_name))
    # 第四步:接收真实的数据,写入文件
    with open(os.path.join(share_dir, file_name), \'wb\') as f:
        recv_size = 0
        while recv_size < file_size:
            line = client.recv(1024)
            f.write(line)
            recv_size += len(line)
            print(\'总大小:%s   已下载大小:%s\' % (bytes2human(file_size), bytes2human(recv_size)))


def put(client, file_name):
    # 向服务端上传文件
    print(\'put\')
    try:
        if not os.path.isfile(os.path.join(share_dir, file_name)):
            print(\'file:%s is not exists\' % os.path.join(share_dir, file_name))
            return
        else:
            file_size = os.path.getsize(os.path.join(share_dir, file_name))
            header_dict = {
                \'file_name\': file_name,
                \'md5\': \'xxx\',
                \'file_size\': file_size

            }

            header_json = json.dumps(header_dict, ensure_ascii=\'False\', indent=2)
            header_bytes = header_json.encode(\'utf-8\')
            # 第二步:先发送报头的长度
            client.send(struct.pack(\'i\', len(header_bytes)))

            # 第三步:再发报头
            client.send(header_bytes)

            # 第四步:再发送真实的数据
            with open(os.path.join(share_dir, file_name), \'rb\') as f:
                for line in f:
                    client.send(line)

    except Exception as e:
        print(e)


def run():
    client = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
    client.connect(IP_PORT)

    while True:
        # 1、发命令
        cmd = input(\'>> \').strip()  # \'get a.txt\'
        if not cmd:continue
        client.send(cmd.encode(\'utf-8\'))

        if cmd.startswith(\'get\'):
            get(client, cmd.split()[1])
        elif cmd.startswith(\'put\'):
            put(client, cmd.split()[1])

    client.close()


if __name__ == \'__main__\':
    run()

 

输出结果

sever:
starting...
(\'127.0.0.1\', 19074)
get
get
C:\Users\jingjing\PycharmProjects\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\server\share\3.jpeg
总大小:75.36K   已上传大小:1.00K
总大小:75.36K   已上传大小:2.00K
……
总大小:75.36K   已上传大小:75.36K


client:


>> get 1.pptx
C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\client\download\1.pptx
总大小:970.93K   已下载大小:1.00K
总大小:970.93K   已下载大小:2.00K
……
总大小:970.93K   已下载大小:970.93K
>> put 3.jpeg
put
>> 

  

传输文件优化版

server端:

import socket
import struct
import json
import os


class TCPServer:

    IP_PORT = (\'127.0.0.1\', 8999)
    request_queue_size = 5
    allow_reuse_address = False
    max_packet_size = 8192

    share_dir = r\'C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\server\share\'

    def __init__(self, address=IP_PORT, bind_and_activate=True):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if bind_and_activate:
            try:
                self.server.bind(address)
                self.server.listen(self.request_queue_size)
                print(\'starting...\')

            except Exception as e:
                self.server.close()
                raise e

    def get_request(self):
        """Get the request and client address from the socket.
        """
        return self.server.accept()

    def run(self):
        while True:
            self.conn, self.client_addr = self.get_request()
            print(\'from client \', self.client_addr)
            while True:
                try:
                    # 1 收命令
                    res = self.conn.recv(self.max_packet_size)  # b\' get a.txt\'
                    if not res: break
                    # 2、解析命令,提取相应命令参数
                    cmds = res.decode(\'utf-8\').split()  # [get, a.txt]
                    if hasattr(self, cmds[0]):
                        func = getattr(self, cmds[0])
                        func(cmds[1])
                except ConnectionResetError:  # 适用于windows操作系统
                    break
            self.conn.close()

        self.server.close()

    def put(self, file_name):
        """
         接收客户端上传文件
        :param conn:
        :param file_name:
        :return:
        """
        print(\'get file %s\' % file_name)

        # 2、以写的方式打开一个新文件,接收客户端发来的文件的内容写入服务端新文件
        # 第一步:先收报头的长度
        header_len = self.conn.recv(4)
        header_size = struct.unpack(\'i\', header_len)[0]

        # 第二步:再收报头
        header_json = self.conn.recv(header_size).decode(\'utf-8\')

        # 第三步:从报头中解析出对真实数据的描述信息
        header_dict = json.loads(header_json)
        file_size = header_dict[\'file_size\']
        file_name = header_dict[\'file_name\']

        print(os.path.join(self.share_dir, file_name))
        # 第四步:接收真实的数据,写入文件
        with open(os.path.join(self.share_dir, file_name), \'wb\') as f:
            recv_size = 0
            while recv_size < file_size:
                line = self.conn.recv(self.max_packet_size)
                f.write(line)
                recv_size += len(line)
                rate = recv_size / file_size * 100
                print(\'总大小:%s   已上传:%%%.2f\' % (self.bytes2human(file_size), rate))

    @staticmethod
    def bytes2human(n):
        symbols = (\'K\', \'M\', \'G\', \'T\', \'P\', \'E\')
        prefix = {}
        for i, s in enumerate(symbols):
            # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
            # 10位就表示1024 即1 << 10=1024 就是2的n次方
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = float(n) / prefix[s]
                return \'%.2f%s\' % (value, s)
        return "%sB" % n

    def get(self, file_name):
        # 3、以读的方式打开文件,读取文件内容发送给客户端
        # 第一步:制作固定长度的报头
        print(\'send file %s\' % file_name)
        try:
            header_dict = {
                \'file_name\': file_name,
                \'md5\': \'xxx\',
                \'file_size\': os.path.getsize(os.path.join(self.share_dir, file_name))

            }

            header_json = json.dumps(header_dict, ensure_ascii=\'False\', indent=2)
            header_bytes = header_json.encode(\'utf-8\')
            # 第二步:先发送报头的长度
            self.conn.send(struct.pack(\'i\', len(header_bytes)))

            # 第三步:再发报头
            self.conn.send(header_bytes)

            # 第四步:再发送真实的数据
            with open(os.path.join(self.share_dir, file_name), \'rb\') as f:
                for line in f:
                    self.conn.send(line)

        except Exception as e:
            print(e)


if __name__ == \'__main__\':
    s = TCPServer()
    s.run()

  

client端:

import socket
import struct
import json
import os


class TCPClient:

    IP_PORT = (\'127.0.0.1\', 8999)
    request_queue_size = 5
    allow_reuse_address = False
    max_packet_size = 8192
    share_dir = r\'C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\client\download\'

    def __init__(self, address=IP_PORT, connect=True):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if connect:
            try:
                self.client.connect(address)
            except Exception as e:
                self.client.close()
                raise e

    def run(self):
        while True:
            # 1、发命令
            inp = input(\'>> \').strip()  # \'get a.txt\'
            if not inp: continue
            self.client.send(inp.encode(\'utf-8\'))
            cmd = inp.split()
            
            if hasattr(self, cmd[0]):
                func = getattr(self, cmd[0])
                func(cmd[1])

        client.close()

    @staticmethod
    def bytes2human(n):
        symbols = (\'K\', \'M\', \'G\', \'T\', \'P\', \'E\')
        prefix = {}
        for i, s in enumerate(symbols):
            # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
            # 10位就表示1024 即1 << 10=1024 就是2的n次方
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = float(n) / prefix[s]
                return \'%.2f%s\' % (value, s)
        return "%sB" % n

    def get(self, file_name):
        # 2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户的新文件
        # 第一步:先收报头的长度
        header_len = self.client.recv(4)
        header_size = struct.unpack(\'i\', header_len)[0]

        # 第二步:再收报头
        header_json = self.client.recv(header_size).decode(\'utf-8\')

        # 第三步:从报头中解析出对真实数据的描述信息
        header_dict = json.loads(header_json)
        file_size = header_dict[\'file_size\']
        file_name = header_dict[\'file_name\']

        print(os.path.join(self.share_dir, file_name))
        # 第四步:接收真实的数据,写入文件
        with open(os.path.join(self.share_dir, file_name), \'wb\') as f:
            recv_size = 0
            while recv_size < file_size:
                line = self.client.recv(self.max_packet_size)
                f.write(line)
                recv_size += len(line)
                rate = recv_size / file_size * 100
                print(\'总大小:%s   已下载:%%%.2f\' % (self.bytes2human(file_size),rate))

    def put(self, file_name):
        # 向服务端上传文件
        print(\'put\')
        try:
            if not os.path.isfile(os.path.join(self.share_dir, file_name)):
                print(\'file:%s is not exists\' % os.path.join(self.share_dir, file_name))
                return
            else:
                file_size = os.path.getsize(os.path.join(self.share_dir, file_name))
                header_dict = {
                    \'file_name\': file_name,
                    \'md5\': \'xxx\',
                    \'file_size\': file_size
    
                }
    
                header_json = json.dumps(header_dict, ensure_ascii=\'False\', indent=2)
                header_bytes = header_json.encode(\'utf-8\')
                # 第二步:先发送报头的长度
                self.client.send(struct.pack(\'i\', len(header_bytes)))
    
                # 第三步:再发报头
                self.client.send(header_bytes)
    
                # 第四步:再发送真实的数据
                with open(os.path.join(self.share_dir, file_name), \'rb\') as f:
                    for line in f:
                        self.client.send(line)
    
        except Exception as e:
            print(e)


if __name__ == \'__main__\':
    c = TCPClient()
    c.run()

  

输出结果:

 

sever:
starting...
from client  (\'127.0.0.1\', 3500)
send file 3.jpeg
get file 1.pptx
C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\server\share\1.pptx
总大小:970.93K   已上传:%0.82
……
总大小:970.93K   已上传:%99.96
总大小:970.93K   已上传:%100.00


client:
 C:/py3Project/路飞/第三模块/第二章网络编程/05_文件传输/简单版本/client/file_client.py
>> get 3.jpeg
C:\py3Project\路飞\第三模块\第二章网络编程\05_文件传输\简单版本\client\download\3.jpeg
总大小:75.36K   已下载:%10.62
……
总大小:75.36K   已下载:%99.49
总大小:75.36K   已下载:%100.00
>> put 1.pptx
put
>> 

  

  

分类:

技术点:

相关文章:

  • 2021-09-20
  • 2022-12-23
  • 2022-12-23
  • 2021-11-04
  • 2021-11-23
  • 2022-03-10
  • 2022-12-23
猜你喜欢
  • 2021-07-30
  • 2021-06-09
  • 2022-12-23
  • 2022-12-23
  • 2021-09-19
  • 2021-09-29
相关资源
相似解决方案