练习:基于TCP协议实现一个网盘系统

一. 题目介绍

请基于TCP协议实现一个网盘系统,包含客户端、服务端,各自需求如下:

  • 客户端

  • 用户注册,注册成功之后,在服务端的指定目录下为此用户创建一个文件夹,该文件夹下以后存储当前用户的数据(类似于网盘)。

  • 用户登录

  • 查看网盘目录下的所有文件(一级即可),ls命令

  • 上传文件,如果网盘已存在则重新上传(覆盖)。

  • 下载文件(进度条)

先判断要下载本地路径中是否存在该文件。

  • 不存在,直接下载

  • 存在,则让用户选择是否续传(继续下载)。

  • 续传,在上次的基础上继续下载。

  • 不续传,从头开始下载。

服务端

  • 支持注册,并为用户初始化相关目录。

注册成功之后,将所有用户信息存储到特定的Excel文件中

  • 支持登录

  • 支持查看当前用户网盘目录下的所有文件。

  • 支持上传

  • 支持下载

二.设计思路

  1. 服务端代码模块设计思路,可以实现单服务功能和多服务兼容功能。

设计思路代码体现:

python 复制代码
class PanHandler(object):
    """ 业务功能代码 """
    def execute(self):
        pass

class Server(object):
    """ 基于普通socket的服务端 """

    def run(self, handler_class):
        # socket服务端
        # 一旦接受到请求之后,就让他执行 PanHandler
        instance = handler_class()
        instance.execute()
        pass

class SelectServer(object):
    """ 基于IO多路复用的socket的服务端 """

    def run(self, handler_class):
        # socket服务端(IO多路复用)
        # 一旦接受到请求之后,就让他执行 PanHandler
        instance = handler_class()
        instance.execute()
        pass


if __name__ == '__main__':
    server = Server()
    # server = SelectServer()
    server.run(PanHandler)

上述代码缺点就是:基于IO多路复用的socket的服务端的server里面的代码处理逻辑相对于普通的socket的服务端还是比较复杂的,为了兼容二者之间的差异,可以做兼容2种服务的代码优化:

python 复制代码
import socket
import select


class PanHandler(object):
    """ 业务功能代码 """

    def __init__(self, conn):
        self.conn = conn

    def execute(self):
        """
        处理客户端的请求
        :return:  False,断开连接;True,继续执行当前客户端发来的请求。
        """
        data = self.conn.recv(1024)

        content = data.decode('utf-8')

        if content.upper() == "Q":
            return False

        # 1.处理登录
        # "login wupeiqi xxx"

        # 2.注册
        # register wupeiqi xxx

        # ....

        self.conn.sendall(b'xxxx')

        return True


class Server(object):
    """ 基于普通socket的服务端 """

    def run(self, handler_class):
        # socket服务端
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind(("IP", "端口"))
        sock.listen(5)

        while True:
            # 等待,客户端发来连接
            conn, addr = sock.accept()

            # 新客户端到来。 PanHandler对象
            instance = handler_class(conn)
            # 处理客户端的请求。 PanHandler对象.execute
            while True:
                result = instance.execute()
                if not result:
                    break

            conn.close()

        sock.close()


class SelectServer(object):
    """ 基于IO多路复用的socket的服务端 """

    def run(self, handler_class):
        server_object = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_object.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_object.setblocking(False)
        server_object.bind(("IP", "端口"))
        server_object.listen(5)


        socket_object_list = [server_object, "客户端socket对象1","客户端socket对象2" ]


        conn_handler_map = {
            "客户端socket对象1": PanHandler(conn1),
            "客户端socket对象2": PanHandler(conn2),
        }

        while True:

            # r = ["客户端socket对象4", ]
            r, w, e = select.select(socket_object_list, [], [], 0.05)

            for sock in r:
                # sock="客户端socket对象4"

                # 新连接到来,执行 handler的 __init__ 方法
                if sock == server_object:
                    print("新客户端来连接")
                    conn, addr = server_object.accept()
                    socket_object_list.append(conn)
                    # 实例化handler类,即:类(conn)
                    conn_handler_map[conn] = handler_class(conn)
                    continue

                # 一旦有请求发来,找到相关的 handler对象,执行他的 execute方法。
                #  execute方法返回False,则意味着此客户端要断开连接。
                handler_object = conn_handler_map[sock]   # 自己PanHandler(conn1),

                # 找到execute去处理各自的业务逻辑
                result = handler_object.execute()
                if not result:
                    socket_object_list.remove(sock)
                    del conn_handler_map[sock]

        sock.close()


if __name__ == '__main__':
    # server = Server()
    server = SelectServer()
    server.run(PanHandler)
相关推荐
七夜zippoe13 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥13 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
Fcy64814 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满14 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
主机哥哥15 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Harvey90315 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技16 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀16 小时前
Linux环境变量
linux·运维·服务器
zzzsde16 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器