<远程教育系统>体系结构设计
因为是一个C/S结构,所以 客户端--服务器端
使用自己的协议:
初步考虑在结构上分为两层:核心层和界面层。这两层是独立的,由核心层触发事件到界面层,核心层只处理了登录的流程,因为登录操作是不需要界面参与的(在提供了密码之后),之后的事件如何处理需要上层程序来实现。所以核心层号称是可重用的.(服务器端客户端都可用)
总体结构概览
核心层定义了一套事件,其包含在TCEvent中,通过实现TCListener接口,界面层可以接收到这些具体的事件,从而做出相应的动作。这是最基本的Observer模式,是我为了把界面和协议分离开来的一种设计考虑。因此系统的总体结构非常简单,如下图所示:
核心层
核心层主要负责协议的解析,网络方面的处理和事件的触发工作。但是这些不是混杂在一起的,比如网络处理,这个功能和其他功能也是相对独立的,所以我首先就需要实现一个稳定的网络层,要做到这个网络层和协议也是无关的,所以,网络层只负责接收纯数据,它不知道包的格式是什么,它只关心是不是收到了一个包,然后网络层会把包推向上层,这个推的动作也是用事件来实现的,也就是PacketEvent。下图是核心层的结构:
协议层通过实现PacketListener接口来得到PacketEvent,然后协议层会判断这个包的格式,从而触发相应的TCEvent。
核心层子层1:网络层
网络层是一个很重要的部分,它必须要足够的稳定.
网络层有一些关键性的需求需要满足:
- 基本的发送接收功能
- 要支持重发功能
- 要支持TCP和UDP
- 要支持代理
在描述如何满足这些需求之前, 给出网络层结构图:
总之,Selector在这里的功能是监听若干个端口,并且触发Read,Write和Connect这三种事件。当一个网络连接有数据可读时,Read事件就触发,当网络连接建立时,Connect会被触发,Write事件有些特殊,一个网络连接在大部分情况下都是可写的,所以Write事件会不断的发生,你就可以随时得到写的机会.
从图中,我们可以看到一些问题的解决办法:
- 1. 使用了发送和接收队列来保存网络包,发送和接收的操作都是在特定的线程里面进行的,这样的话,网络操作不会造成界面上的堵塞
- 2. 为了支持重发功能,还使用了一个重发队列,在每个包发送出去之后,这个包都会被添加到重发队列里面,有一个Resender类会维护这个重发队列,并且在包超时之后把它再次推入发送队列。为了避免不必要的重发,Resender提供了删除重发包的方法供协议层调用。另外,Resender也会触发PacketEvent,其类型主要都是超时事件。图中并没有画出。
- 3. 有一个PacketEvent的触发器,它运行在一个单独的线程中,每当接收队列中有包的时候,这个线程会被唤醒,从而触发PacketEvent。
- 4. 任何上层的网络操作都不是直接的,它们都是把要发送的包推入发送队列,然后等待INIOHandler接口的实现类把这个包取走并发送出去。所以只有INIOHandler的实现类是直接存取网络的。
- 5. INIOHandler接口定义了读写的方法,其不关心协议,所以我们可以为UDP协议实现一个INIOHandler,可以为TCP协议实现一个INIOHandler,这样就实现了对多种协议的支持,对于代理,也同样处理,只不过代理还有IProxy和IProxyHandler接口,我们不深究这些接口,因为它们只不过是处理连接代理的过程而已,最关键的还是这个INIOHandler接口,它是网络层实现的核心。
核心层子层2:协议层
协议层从接收到PacketEvent开始,到触发TCEvent为止,完成了它的工作流程。所以这个流程比网络层简单多了,没有那么多烦人的队列,没有那么多监听的线程。协议层只有非常简单的结构加上一些冗长的条件判断。协议层的核心是PacketProcessor,它接收PacketEvent,然后判断包的类型,从而触发TCEvent。触发TCEvent的线程和触发PacketEvent的线程是同一个线程,而这个线程也会一直运行到界面层,对于SWT来说,就需要注意修改界面的操作只能在UI线程中执行。
TCClient类是整个核心层的入口,通过这个类,上层程序可以和核心层交互,TCClient采用的是Facade模式,其提供了大量的封装方法,上层程序基本不关心核心层其他类(文件传送时有些例外)。
界面层
界面层有待商催..是使用类似QQ的界面呢还是什么好呢?晕
ps:以上是我在看了LumaQQ的结构时想到的一些关于我要做的软件的解决方案