非阻塞式网络通信

来源:互联网 发布:gmc中文编程下载 编辑:程序博客网 时间:2024/04/30 14:39

年前的时候一直在做架构方面的工作。实际上就是规划客户端的程序结构。

一般的网络请求的客户端采用“一对一”的形式。即开始网络请求,类似于网络浏览器,在请求新的结果时,需要先取消前一个网络请求。这样的过程对于早先的手机客户端是可以接受的。随着手机客户端逻辑越来越复杂,这种单一的请求模式必然不能满足需要。因此,原浏览器式的请求需要改进。

在做改进的时候,开始研究底层的通讯代码,发现此代码与网上的比较火的google浏览器写法极其相似。采用任务列表的方式,将所有的动作(函数)作为指针发送到任务处理中心,任务处理中心依次处理这些任务。此方法将多线程的通讯过程简化到一个单线程中,比较给力。

但是这个程序写的太复杂了,看了好久才懂,出了问题都不敢乱改。因此还是不想用此代码。

一直尝试这样的架构,网络层来数据收就好了,客户端需要数据请求就好了,等数据来了,再显示出来,发送和接收完全分离。

最终还是需要网络模块给力才行。以前写过阻塞式的通讯模块。大致思路为每个连接两个线程,一个线程用来发送,一个线程用来接收数据。对于客户端而言,连接和发送为同一个线程。

客户端:

用一个类TcpSocketClient来封装客户端的相关信息,每个类实例表示一个连接,可以考虑用同步连接的形式完成连接,连接完成后进行数据的发送。在连接完成后,需要通过WSAEventSelect进行事件的注册。然后开启一个事件响应线程,在那儿进行数据的接收。

为了提高效率和简化外界的使用,可以在外面加一层包装类TcpSocketPool,此类是一个连接池,当发现存在可以重复使用类实例时(这些类实例是由于连接断开,为了重复利用没有被销毁,便可以直接使用旧有的连接实例,而无需创建新的实例,减少了重复创建和销毁的开销。

可以固定下与外界的接口。HRESULT Write(const char* addr, int port, const char* data);这样,当需要发送给指定服务器数据时,直接通过此函数进行,由它去检查是否已经完成连接,未完成连接,则先进行连接操作。

 

服务器:

用一个类来封装服务器的相关信息,一个类实例用来处理一条连接。第一个实例用来侦听,从第二个开始来进行数据的传输。每一个实例产生一个事件线程。第一个实例专用来侦听accapt事件,发现有新的连接,则创建一个新的实例,以完成后续的数据的接收和发送。

原创粉丝点击