首页 > 编程语言 > 详细

Python学习第58天(selector版本的ftp习题实现)

时间:2020-04-21 01:00:06      阅读:93      评论:0      收藏:0      [点我收藏+]

  本来打算开始web前端的学习的,但是布置的习题还是应该做一下的,花了不少时间,貌似还有一个功能没有完成,但是重点已经有了,其实先来回顾一下昨天引入的这个selector模块吧,说说里面的重点。  

import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print(accepted, conn, from, addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        print(echoing, repr(data), to, conn)
        conn.send(data)  # Hope it won‘t block
    else:
        print(closing, conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind((localhost, 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)

  这里应该注意的句式,就是

    sel = selectors.DefaultSelector()

    sel.register(sock, selectors.EVENT_READ, accept)

  这两句就是绑定了监测对象,sock发生变化时候,就会执行accept

技术分享图片

 

   大致就是个这么个意思,监测的对象可以是events是个对象列表,不止一个会发生变化,所以要利用for循环遍历,保证每次都能将每个有变化的conn接收到信息

  然后后面的习题就是通过这个特性实现的

  sel.register(sock, selectors.EVENT_READ, accept)把sock加入了监测列表,accept函数又把conn加入了监测列表

  好了,知识会议的差不多了,上干货,干了三个小时的杰作:

  客户端:

import socket
import os,sys
BASE_DIR = os.path.dirname(os.path.abs(__file__))

class selectFtpClent:

    def __init__(self):
        self.args = sys.argv
        if len(self.args) > 1:
            self.port = (self.args[1],int(self.args[2]))
        else:
            self.port = (127.0.0.1, 8080)
        self.creat_socket()
        self.command_fanout()

    def creat_socket(self):
        try:
            self.sk = socket.socket()
            self.sk.connect(self.port)
            print(连接FTP服务器成功)
        except Exception as e:
            print(error: ,e)


    def command_fanout(self):
        while True:
            cmd = input(输入命令>>>)
            if cmd == exit():
                break
            cmd,file = cmd.split()
            if hasattr(self, cmd):
                func = getattr(self,cmd)
                func(cmd,file)
            else:
                print(命令错误)


    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.sk.send(bytes(fileInfo,encoding = utf-8))
            recvStatus = self.sk.recv(1024)
            print(recvStatus: , recvStatus)

            has_send = 0
            if str(recvStatus, encoding =  utf-8) == OK:
                with open(file, rb) as f:
                    while fileSize > has_send:
                        contant = f.read(1024)
                        recv_size = len(contant)
                        self.sk.send(contant)
                        has_send +=recv_size
                        s = str(int(has_send/fileSize)) + %
                        print(正在上传文件:+ fileName + 已上传 + s)
                print(%s文件上传完毕%%fileName)
            else:
                print(文件不存在)

    def get(self):
        pass

if __name__ == __main__:
    selectFtpClent()

  服务端:

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

class selectFtpServer:

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

    def creat_socket(self):
        server = socket.socket()
        server.bind((127.0.0.1 , 8080))
        server.listen(5)
        server.setblocking(False)
        self.sel.register(server, selectors.EVENT_READ, self.accept)
        print(服务器已开启,等待用户连接......)

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

    def accept(self,sock,mask):

        conn, addr = sock.accept()
        print(from %s %s connected%addr)
        conn.setblocking(False)
        # 作为后面conn的标记,防止很多conn的一个标记,同时记录相关信息
        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)} }

                if cmd == put:
                    conn.send(bytes(OK,encoding = utf-8))

                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 = utf-8))
                    else:
                        send_info = %s|%s%(NO,0)
                        conn.send(bytes(send_info, encoding=utf-8))

            else:
                if self.dic[conn].get(cmd,None):
                    cmd = self.dic[conn].get(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)




    def put(self,conn):

        file_name = self.dic[conn][filename]
        file_size = self.dic[conn][filesize]
        path = os.path.join(BASE_DIR,upload,file_name)
        recv_data = conn.recv(1024)
        self.hasReceived += len(recv_data)

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

    def get(self,conn):
        pass

if __name__ == __main__:
    selectFtpServer()

  虽然get方面目前还是pass,但是这个都是简单模式,关键是搞定了多客户的同时传递,避免socketserver模块一次存在的一些弊端,比如多用户分别占用的问题

  嗯,明天就要开始web前端了,激动。。。

Python学习第58天(selector版本的ftp习题实现)

原文:https://www.cnblogs.com/xiaoyaotx/p/12741611.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!