Python socket文件上传下载

python网络编程

程序的目录结构

socketDemo
├── client
│   ├── cli.py
│   └── local_dir
│       └── lianxijiangjie.mp4
└── server
    ├── download
    │   └── lianxijiangjie.mp4
    └── ser.py

 

基础版本

ser.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'mosson'
import socket
import struct
import json
import os

base_dir = os.path.dirname(os.path.abspath(__file__))
base_dir = os.path.join(base_dir, 'download')


class MYTCPServer:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    allow_reuse_address = False
    max_packet_size = 8192
    coding='utf-8'
    request_queue_size = 5
    server_dir='file_upload'

    def __init__(self, server_address, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        self.server_address=server_address
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

    def server_bind(self):
        """Called by constructor to bind the socket.
        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()

    def server_activate(self):
        """Called by constructor to activate the server.
        """
        self.socket.listen(self.request_queue_size)

    def server_close(self):
        """Called to clean-up the server.
        """
        self.socket.close()

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

    def close_request(self, request):
        """Called to clean up an individual request."""
        request.close()

    def run(self):
        print('server is running .......')
        while True:
            self.conn,self.client_addr=self.get_request()
            print('from client ',self.client_addr)
            while True:
                try:
                    head_struct = self.conn.recv(4)
                    if not head_struct:break

                    head_len = struct.unpack('i', head_struct)[0]
                    head_json = self.conn.recv(head_len).decode(self.coding)
                    head_dic = json.loads(head_json)

                    print(head_dic)
                    cmd=head_dic['cmd']
                    if hasattr(self,cmd):
                        func=getattr(self,cmd)
                        func(head_dic)
                except Exception:
                    break

    def put(self,args):
        """
        文件长传
        :param args:
        :return:
        """
        file_path=os.path.normpath(os.path.join(
            base_dir, args['filename']))

        filesize=args['filesize']
        recv_size=0
        print('----->',file_path)
        with open(file_path,'wb') as f:
            while recv_size < filesize:
                recv_data=self.conn.recv(2048)
                f.write(recv_data)
                recv_size += len(recv_data)
            else:
                print('recvsize:%s filesize:%s' %(recv_size,filesize))

    def get(self, args):
        """ 下载文件
        1 检测服务端文件是不是存在
        2 文件信息 打包发到客户端
        3 发送文件
        """
        filename = args['filename']
        dic = {}
        if os.path.isfile(base_dir + '/' + filename):
            dic['filesize'] = os.path.getsize(base_dir + '/' + filename)
            dic['isfile'] = True
        else:
            dic['isfile'] = False
        str_dic = json.dumps(dic) # 字典转str
        bdic = str_dic.encode(self.coding) # str转bytes
        dic_len = len(bdic) # 计算bytes的长度
        bytes_len = struct.pack('i', dic_len) # 
        self.conn.send(bytes_len) # 发送长度
        self.conn.send(bdic)  # 发送字典
        # 文件存在发送真实文件
        if dic['isfile']:
            with open(base_dir + '/' + filename, 'rb') as f:
                while dic['filesize'] > 2048:
                    content = f.read(2048)
                    self.conn.send(content)
                    dic['filesize'] -= len(content)
                else:
                    content = f.read(2048)
                    self.conn.send(content)
                    dic['filesize'] -= len(content)
            print('下载完成')


tcpserver1=MYTCPServer(('127.0.0.1',8083))

tcpserver1.run()
服务端代码

cli.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'mosson'

import socket
import struct
import json
import os
import time

base_dir = os.path.dirname(os.path.abspath(__file__))
base_dir = os.path.join(base_dir, 'local_dir')


class MYTCPClient:
    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    allow_reuse_address = False

    max_packet_size = 8192

    coding='utf-8'

    request_queue_size = 5

    def __init__(self, server_address, connect=True):
        self.server_address=server_address
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if connect:
            try:
                self.client_connect()
            except:
                self.client_close()
                raise

    def client_connect(self):
        self.socket.connect(self.server_address)

    def client_close(self):
        self.socket.close()

    def run(self):
        while True:
            inp=input(">>: ").strip()
            if not inp:continue
            l=inp.split()
            cmd=l[0]
            if hasattr(self,cmd):
                func=getattr(self,cmd)
                func(l)


    def put(self,args):
        cmd=args[0]
        filename = args[1]
        filename = base_dir + '/' + filename
        print(filename)
        if not os.path.isfile(filename):
            print('file:%s is not exists' %filename)
            return
        else:
            filesize=os.path.getsize(filename)

        head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
        print(head_dic)
        head_json=json.dumps(head_dic)
        head_json_bytes=bytes(head_json,encoding=self.coding)

        head_struct=struct.pack('i',len(head_json_bytes))
        self.socket.send(head_struct)
        self.socket.send(head_json_bytes)
        send_size = 0
        t1 = time.time()
        # with open(filename,'rb') as f:
        #     for line in f:
        #         self.socket.send(line)
        #         send_size+=len(line)
        #     else:
        #         print('upload successful')
        #         t2 = time.time()
        with open(filename, 'rb') as f:
            while head_dic['filesize'] > 2048:
                content = f.read(2048)
                self.socket.send(content)
                head_dic['filesize'] -= len(content)
            else:
                content = f.read(2048)
                self.socket.send(content)
                head_dic['filesize'] -= len(content)
            t2 = time.time()

            

        
        print(t2-t1)

    def get(self, args):
        cmd = args[0]
        filename = args[1]
        dic = {'cmd': cmd, 'filename': filename}
        """发送dic的步骤
        字典转str
        str转bytes
        计算bytes的长度
        发送长度
        发送字典
        """
        str_dic = json.dumps(dic) # 字典转str
        bdic = str_dic.encode(self.coding) # str转bytes
        dic_len = len(bdic) # 计算bytes的长度
        bytes_len = struct.pack('i', dic_len) # 
        self.socket.send(bytes_len) # 发送长度
        self.socket.send(bdic)  # 发送字典

        # 接受 准备下载的文件信息
        dic_len = self.socket.recv(4)
        dic_len = struct.unpack('i', dic_len)[0]
        dic = self.socket.recv(dic_len).decode(self.coding)
        dic = json.loads(dic)
        # 文件存在准备下载
        if dic['isfile']:
            t1 = time.time()
            with open(base_dir+'/'+filename, 'wb') as f:
                while dic['filesize'] > 2048:
                    content = self.socket.recv(2048)
                    f.write(content)
                    dic['filesize'] -= len(content)
                else:
                    while dic['filesize']:
                        content = self.socket.recv(2048)
                        f.write(content)
                        dic['filesize'] -= len(content)
                    t2 = time.time()
            print(t2-t1)

        else:
            print('文件不存在!')




client=MYTCPClient(('127.0.0.1',8083))

client.run()
客户端代码

 

升级版本

。。。。。。。。

 

 

 

 

==================== 码字不易,如有帮助,请多多支持 ====================

 

posted @ 2019-06-27 17:06  想做土匪的书生  阅读(981)  评论(1编辑  收藏  举报