大作业 - 3 服务器结构设计

服务器架构

对于单个树莓派,可能会有多个观看者,但是为了操作的安全性考虑,只能有一个操作者。

大作业 - 3 服务器结构设计_第1张图片
单树莓派结构图

而我们这个项目需要有多个树莓派,并且需要通过服务器进行信息周转,但是每个树莓派只需要接收到来自唯一操控者的消息即可。所以需要服务器进行一些过滤工作,这就需要一些权限控制。

大作业 - 3 服务器结构设计_第2张图片
实际连入方式

数据结构设计

首先,每个树莓派的连接都必须进行存储。代码中,使用一个Connection类的实例对应一个树莓派的连接,并在生成的同时列入连接集合中方便查找。

同时,每个树莓派会接受许多的用户接入,为了信息广播的方便,需要有存放每个连入的用户。即整体结构为服务器下属多个树莓派,而每个树莓派包含多个用户。

其次,不能光存储连接,作为用户要使用树莓派,不仅仅是按按键而已,同时也需要进行文件的传输,而每个树莓派所下载的文件也是不一样的。所以,也需要每个树莓派的连接各自存放文件的信息。

树莓派所存储的文件可以直接写在硬盘上,使用时再通过socket或者http方式传递给树莓派,但是可能会带来安全性的问题。考虑到*.bit文件大小较小,所以决定将文件直接存放于内存中。(Update: 由于新增一些需求,最新版本将文件写在硬盘中,默认路径为/tmp/exotic/)

上述结构对应的代码如下。其中_user字段中的admin表示当前树莓派的操作者的连入句柄,只有这个句柄所属的用户发送的信息才可以被服务器转发给树莓派。

class Connection(object):
    # 以list的形式存储客户端
    # KeepList保证在remove的时候,不改变其余所有项目的位置
    # 而是选择在原处留下删除印记,客户端的句柄会优先放置在有印记的位置
    client = KeepList()

    def __init__(self, stream, address):
        # 存储下当前客户端的有关信息
        self._stream = stream
        self._address = address
        self._stream.set_close_callback(self.on_close)

        # 将客户端加入list并存储客户端在list中的位置
        self._index = Connection.client.append(self)

        # 记录所有用户的句柄,并标示出操作者
        self._user = dict(
            admin = None, # 操作者句柄
            lock = thread.allocate_lock(), # 操作者切换时的同步锁
            user = set()  # 所有连入用户的集合
        )

        # 将上传的文件保存在内存
        self._file = dict(
            name = '',
            body = None
        )
        
        ......

参考资料

  • Python Socket 编程——聊天室示例程序

你可能感兴趣的:(大作业 - 3 服务器结构设计)