基于python标准库socket流和结构体struct的ftp文件上传和下载

1 目录

说明下:文件上传成功,但是pycharm没显示文件,需要刷新,其实桌面文件夹upload里面早就有了

2 先启动的服务端

import socket
import struct
import json
import os

base_path = os.path.dirname(os.path.abspath(__file__))


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

    #上传文件地址
    server_dir = os.path.join(base_path, 'upload')
    print(server_dir)

    def __init__(self, server_address, bind_and_listen=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_listen:
            try:
                self.server_bind()
                self.server_listen()
            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_listen(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):
        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_content = self.conn.recv(head_len).decode(self.coding)
                    head_data = json.loads(head_content)

                    print(head_data)
                    #head_data={'cmd':'put','filename':'a.txt','filesize':123123}
                    cmd = head_data['cmd']
                    if hasattr(self, cmd):
                        func = getattr(self, cmd)
                        func(head_data)
                except Exception:
                    break

    def put(self, args):
        file_path = os.path.normpath(os.path.join(self.server_dir, args['filename']))

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


if __name__ == '__main__':
    tcpserver = MYTCPServer(('127.0.0.1', 9090))
    tcpserver.run()

3 后启动的客户端以及客户端输入download文件夹下的hello.txt文件

import socket
import struct
import json
import os

base_path = os.path.dirname(os.path.abspath(__file__))

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):
        """example: put /Users/Alex/Desktop/ftp/download/hello.txt"""
        while True:

            print("format input:put /Users/Alex/Desktop/ftp/download/hello.txt")
            cmd_args = input(">>:").strip()
            if not cmd_args:
                continue
            cmd_args_list = cmd_args.split()
            cmd = cmd_args_list[0]
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                func(cmd_args_list)

    def put(self, args):
        cmd = args[0]
        filename = args[1]
        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)
        print(head_dic)

        head_struct = struct.pack('i',len(head_json_bytes))
        print("lenth of head_struct:", len(head_struct))
        # 4
        self.socket.send(head_struct)
        print("head_struct:", head_struct)
        self.socket.send(head_json_bytes)
        print("head_json_bytes:", head_json_bytes)

        send_size = 0
        with open(filename, 'rb') as f:
            for line in f:
                self.socket.send(line)
                send_size += len(line)
                print(send_size)
            else:
                print('upload successful')

if __name__ == '__main__':
    client = MYTCPClient(('127.0.0.1', 9090))
    client.run()

4 基本操作

启动服务端和客户端后,在客户端执行:put /Users/Alex/Desktop/ftp/download/hello.txt   具体路径改成你自己的路径

 

posted @ 2018-08-15 17:04  Adamanter  阅读(377)  评论(0编辑  收藏  举报