距离上一篇总结也几天了,一直没时间缕清楚一些实现细节,今天就边学习边写,彻底结束这个项目。
异步通信模型
本项目中,socketserver网络监听线程中使用了一个异步的通信模型,这样就可以做到在有新的网络连接时不用开启新的线程,从而减小系统开销。这个地方,其实我对于它的实现机制还是很疑惑的,怎么可能做到不开启新的线程就在主线程执行时同时处理新的网络连接,这个从原理上来说不建立新的线程是无法实现的,总之就是不科学的。
为了解决这个问题,我首先研究了一下c#中异步通信的实现机制。简单来说,它是通过异步回调函数来实现的。
程序中在完成了一个socket的初始化,绑定端口后,就可以调用它的监听函数accept()进行监听,调用这个函数是同步的,不是异步的。为了实现异步的监听,sokcet调用beginaccept这个函数,这个函数的参数中需要注册一个异步回调函数,这个异步回调函数就是异步通信模型的实现方式,它实现了异步通信模型。同时,这个异步回调函数中需要调用这个socket的endaccept()这个函数结束这个socket的监听,反之建立一个新的socket并且返回,然后我们使用这个新的socket继续进行监听。这个socket会注册和原来一样的异步回调函数来处理新的连接。
好的,通过上面说的,我们知道了,异步通信模型是通过异步回调函数来实现的,这里没有新建线程,那么问题来了,这个异步回调函数是怎么实现的呢?它怎么就可以做到不新建线程的呢?下面我们继续向下研究,先前我猜测异步回调函数是通过中断主线程的执行来实现的,但是后来想到,这个不合常理,特别是在网络连接这种情况下。如果在这里中断的话,那就是说后来的网络连接会中断前面的网络连接,这么做完全不符合逻辑。问题到了这里其实已经转换到了异步函数的实现机制上来了。在c#中异步的实现机制被隐藏了,我查过一个资料发现,有人认为异步底层是通过新建线程实现的,只不过在我们所见的层面上没有建立线程。好吧,这样就符合逻辑了。这是一种说法,我认为是对的,异步的实现是需要线程的。至于正确与否,还得研究啊。
托管
托管(delegate)是c#中一个重要的概念,类似于c++中的函数指针。貌似托管还有一些其他应用,不过暂时没有对c#进行太多研究的意愿,先不管了,直接说在此处的应用。由于在client中网络连接是使用的子线程,当服务器返回数据时,需要更新主线程的界面,但是子线程无法直接更新主界面,这里就可以使用托管来做这件事情,这个用法与c++中的函数指针是类似的。
通信协议
为了让client与server可以互通信息,需要制定应用专用的通信协议,这个协议还是比较简单的。首先需要头和尾,此处使用##作为头,$$作为尾,应用通过检查头和尾来确定报文信息,使用两个是为了防止报文中有这个符号影响报文数据解析,使用两个这样出现的概率比较小。在头尾之间包括数据包大小和正文,其中大小部分占用4byte,这个是int型的大小,具体数据等正文构造完毕时填写。中文使用“|”来分隔不同的参数,其中client发送到server的数据中正文的前两个参数是用户名和密码,这个是因为我们使用了短连接,每次连接都需要验证身份。其余的参数根据具体的业务需求构造,这里不再赘述。
虽然退出了这个项目,当时做的也不怎么完善,不过好歹可以用了。主要是学习到的东西和经验相信会在以后帮助到我。