练习:基于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)
相关推荐
4311媒体网16 分钟前
帝国CMS网站自定义搭建技巧
服务器·开发语言·前端
Dachui_112235 分钟前
企业内网大模型公网访问方案:Ollama + OpenWebUI + ZeroNews 实战部署记录
运维·服务器·安全·远程工作·内网穿透
2401_890603401 小时前
Linux 进程控制
linux·运维·服务器
雨辰AI1 小时前
openGauss 生产运维避坑指南|适配信创项目改造核心难点
java·运维·后端
小波波啊1 小时前
nginx 转发超时故障排查实录
运维·nginx
2401_865382501 小时前
信息化建设项目申报建设费时运维费能否一起报送?
运维
九硕智慧建筑一体化厂家1 小时前
大型建筑集群智慧管控升级!IBMS系统实现多系统一体化融合管理
运维·人工智能·笔记·智慧城市
HAHAXX81 小时前
低代码 & 无代码 RPA 项目实施:对接大模型接口的部署与运维要点
运维·低代码·rpa
啦啦啦啦啦zzzz2 小时前
时间轮定时器
linux·服务器·网络·c++·定时器
ITyunwei09872 小时前
从 ITIL 视角量化-第三集:工单系统如何成为 ITSM 治理抓手?架构+量化
运维·网络·企业微信