python使用selector模块编写FTP

server

import os
import socket
import time
import selectors
BASE_DIR = os.path.dirname(os.path.abspath(__file__))


class selectFtpServer(object):

    def __init__(self):
        self.dic = {}
        self.hasReceived = 0
        self.sel = selectors.DefaultSelector()
        self.create_socket()
        self.handler()

    def create_socket(self):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind(("127.0.0.1", 8885))
        server.listen(5)
        self.sel.register(server, selectors.EVENT_READ, self.accept)
        print("服务端已开启,等待用户连接...")

    def handler(self):
        while True:
            events = self.sel.select()
            for key, mask in events:
                call_back = key.data
                call_back(key.fileobj, mask)

    def accept(self, server, mask):
        conn, addr = server.accept()
        print("from %s %s connected" % addr)
        self.sel.register(conn, selectors.EVENT_READ, self.read)

        self.dic[conn] = {}

    def read(self, conn, mask):
        try:
            if not self.dic[conn]:
                data = conn.recv(1024)
                cmd, filename, filesize = str(
                    data, encoding='utf-8').split('|')
                self.dic = {
                    conn: {
                        "cmd": cmd,
                        "filename": filename,
                        "filesize": int(filesize)}}
                print(self.dic)
                if cmd == 'put':
                    conn.send(bytes("OK", encoding='utf8'))

                if self.dic[conn]['cmd'] == 'get':
                    file = os.path.join(BASE_DIR, "download", filename)

                    if os.path.exists(file):
                        fileSize = os.path.getsize(file)
                        send_info = '%s|%s' % ('YES', fileSize)
                        conn.send(bytes(send_info, encoding='utf8'))
                    else:
                        send_info = '%s|%s' % ('NO', 0)
                        conn.send(bytes(send_info, encoding='utf8'))
            else:
                if self.dic[conn].get('cmd', None):
                    print(self.dic[conn].get('cmd'))
                    cmd = self.dic[conn].get('cmd')
                    print(cmd)
                    if hasattr(self, cmd):
                        func = getattr(self, cmd)
                        func(conn)
                    else:
                        print("error cmd!")
                        conn.close()
                else:
                    print("error cmd!")
                    conn.close()

        except Exception as e:
            print('error', e)
            self.sel.unregister(conn)
            conn.close()

    def put(self, conn):
        self.hasReceived = 0
        fileName = self.dic[conn]['filename']
        fileSize = self.dic[conn]['filesize']
        path = os.path.join(BASE_DIR, "upload", fileName)
        while self.hasReceived < fileSize:
            recv_data = conn.recv(1024)
            self.hasReceived += len(recv_data)

            with open(path, 'wb') as f:
                f.write(recv_data)
            if fileSize == self.hasReceived:
                if conn in self.dic.keys():
                    self.dic[conn] = {}
                print("%s上传完毕!" % fileName)

    def get(self, conn):

        filename = self.dic[conn]['filename']
        path = os.path.join(BASE_DIR, "download", filename)
        if str(conn.recv(1024), 'utf-8') == "second_active":
            with open(path, 'rb') as f:
                for line in f:
                    conn.send(line)
            self.dic[conn] = {}
            print('文件下载完毕!')


if __name__ == '__main__':
    ftp = selectFtpServer()

  

client

import socket
import time
import os

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


class selectFtpClient():

    def __init__(self):
        self.createSocket()
        self.command_out()

    def createSocket(self):
        try:
            self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client.connect(("127.0.0.1", 8885))
            print('连接FTP服务器成功!')
        except Exception as e:
            print("error: ", e)

    def command_out(self):
        while True:
            cmd = input('>>>').strip()
            if cmd == 'exit':
                break
            cmd, file = cmd.split()
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                func(cmd, file)
            else:
                print('调用错误!')

    def get(self, cmd, file):
        pass

    def put(self, cmd, file):
        if os.path.isfile(file):
            fileName = os.path.basename(file)
            fileSize = os.path.getsize(file)
            fileInfo = '%s|%s|%s' % (cmd, fileName, fileSize)
            self.client.send(bytes(fileInfo, encoding='utf8'))
            recvStatus = self.client.recv(1024)
            print('recvStatus', recvStatus)
            hasSend = 0
            if str(recvStatus, encoding='utf8') == "OK":
                with open(file, 'rb') as f:
                    while fileSize > hasSend:
                        contant = f.read(1024)
                        recv_size = len(contant)
                        self.client.send(contant)
                        hasSend += recv_size
                        s = str(int(hasSend / fileSize * 100)) + "%"
                        print("正在上传文件:" + fileName + "   已经上传:" + s)
                print('%s文件上传完毕' % (fileName,))
        else:
            print('文件不存在')


if __name__ == '__main__':
    c = selectFtpClient()

  

原文地址:https://www.cnblogs.com/xiao-apple36/p/9624245.html