中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)22-5213-04
随着经济和网络的不断发展,桌面广告投放系统已经成为广告宣传的重要方式。个人电脑已经成为办公、收银等处理业务的客户终端,客户终端桌面也是一张名品。利用桌面广告投放系统可将这些客户终端的桌面设置为统一形式,无形中加大了宣传力度。
桌面广告投放系统采用C/S模式,核心是解决一对多的大并发网络连接问题。
1 桌面广告系统结构
桌面广告系统采用C/S网络模型并基于互联网实现服务端和客户端的网络通信。桌面广告系统包括客户端、服务器端和互联网,客户端为需要设置桌面广告的计算机,服务端为产生广告桌面的服务器,通常架设在个人计算机上。系统结构如图1所示。
2 IOCP机制的工作原理
完成端口(IOCP)的核心原理就是将绑定到IOCP的socket发出的异步I/O请求投递到消息队列中,利用一定数量的工作线程从消息队列中取出消息并进行处理,并在工作者线程中返回中间数据。IOCP工作框架如图2所示。
2.1 完成端口
完成端口是windows的内核对象,称其为完成端口,是因为系统在网络I/O操作“完成”之后才会发出通知。在接到系统的通知的时,其实网络操作已经完成,此时,系统已经自动完成网络数据的接收(而不是像传统socket是有网络数据到来)或者系统已经自动接受了客户端的连接请求等等,应用程序的工作就是直接处理接收的网络数据或者判断新连入的客户端。
完成端口的实际处理方式是:依据CPU数量N,建立2*N个线程。这些线程能够充分利用CPU资源,从某一个公共消息队列中循环读取数据,当队列中无数据时,一直处于等待状态。当客户数据或请求到来时,应用程序将客户请求投放到该公共消息队列中。线程们依次逐个从该消息队列中取出用户数据并进行处理。这种处理数据的方式就彻底解决了异步通信中的负载均衡问题。因为它通过一定数量的线程合理的处理大量客户端的请求数据,且当线程处于空闲时期会被系统挂起,不耗费CPU资源。这个作为交换的关键消息队列就是完成端口[3]。
2.2 重叠I/O
利用完成端口实现异步通信,必须使用到极其重要的I/O数据结构,即重叠(Overlapped)结构。
重叠结构是异步通信机制实现的一个核心数据结构,绝大多数网络操作如发送和接收,都将被WSASend()和WSARecv()所代替,每个参数都会包含一个重叠结构。在使用重叠I/O的异步机制时,系统内核要求每个网络操作都必须有唯一的ID号。而重叠结构就相当于是一个网络操作的ID号,内核中进入重叠I/O后,按需求处理完毕,再根据其ID号,把对应的数据传到内核外。
3 系统的工作流程及实现
3.1 工作流程
利用IOCP模型开发网络服务端,主要的工作就是创建主线程和工作线程。在异步通信中,主线程主要的任务就是初始化时建立通信框架,即创建并监听套接字,创建工作线程,等待客户端连接。工作线程主要处理IOCP上完成的网络操作。本系统的服务端功能模块在VC6环境中开发,利用socket模型中的TCP/IP协议,网络传输工作过程如图3所示流程。
3.2 实现过程
定义单句柄数据结构体,用于每一个完成端口,也就是每一个Socket的参数。具体结构定义如下:
大体上来讲,使用完成端口只用遵循如下几个步骤:
1) 调用 CreateIoCompletionPort() 函数创建一个完成端口,而且在一般情况下,只需要建立一个完成端口。
2) 根据系统中有多少个处理器,就建立多少个工作者线程;
3) 接收客户端socket连接,共有两种处理方法:一是启动一个独立的线程,接受客户端的连接请求;二是使用异步AcceptEx()请求。该文采用第二种方式。
4) 每当有客户端连入的时候,调用CreateIoCompletionPort()函数,这里却不是新建立完成端口了,而是把新连入的Socket(也就是前面所谓的设备句柄),与目前的完成端口绑定在一起。至此,就已经完成了完成端口的相关部署工作了。
5) 客户端连入之后,可以在这个Socket上提交一个网络请求,例如WSARecv(),然后系统就会自动去执行接收数据的操作;
6) 而此时,预先准备的那几个Worker线程开始工作,都需要分别调用GetQueuedCompletionStatus() 函数在扫描完成端口的队列里是否有网络通信的请求存在(例如读取数据,发送数据等),一旦有的话,就将这个请求从完成端口的队列中取回来,继续执行本线程中后面的处理代码,处理完毕之后,可以再继续投递下一个网络通信的请求,如此循环。
4 关键问题处理
4.1服务器搭建
在互联网上通过C/S模型实现网络通信,首要的问题是服务器的搭建。普通使用者的需要的是方便、便宜的服务器。
本系统服务端所在主机通过使用花生壳动态域名6.0将本地主机设置为服务器,如图4所示。花生壳动态域名软件通过注册的域名动态生成本机的IP地址,客户端以服务器域名为参数利用API函数gethostbyname()获得服务器的IP,通过指定的端口与服务端建立网络连接。
4.2包排序接收信息重组处理
在接收各子系统网络报文数据时,由于TCP/IP协议对数据的封装操作,导致报文数据在网络传输过程重新组合、打包发送,存在以下情况:1一帧数据被拆分,附在其他报文数据的帧头或者帧尾打包;2前一帧数据同下一帧或几帧报文一起打包。为避免出现采用网络传送数据过程中的“丢帧”现象,根据数据帧的报文结构,对接收的报文数据进行解析处理,重新组合成一帧完整的报文,处理流程如图5所示[4]。
4.3 传送文件
利用Winsock提供的专门传输文件和内存数据的函数TransmitFile()传输时,只需要传递已打开的文件句柄和要发送的字节数。转换模式操作只在调用CreateFile()打开文件时发生一次,然后TransmitFile()再发生一次。这样的效率相比每次都调用ReadFile()和WSASend()都会涉及一次从用户模式到内核模式的转换要高多了。
5 结论
本系统服务端采用IOCP模型,只需要少量的工作线程来完成大量的网络操作,且线程的数量随CPU数量线性增加。该文设计的桌面广告投放系统可以高效得处理多并发,解决了客户端连接量巨大,小容量数据频繁收发的问题,实现了桌面投放系统的初步功能。通过测试,该系统可以满足大并发量的桌面投放要求。
参考文献:
[1] 王震,徐博,等.单客户机-多服务器模式下IOCP的应用与研究[J].计算机科学,2011(10):385-386.
[2] Jose Vitor . Another TCP echo server using IOCP [EB/OL]. (2013-03-27). http://www.codeproject.com/Tips/95363/Another-TCP-echo-server-using-IOCP.
[3] 树爱兵,徐棱,等.IOCP机制在交通信号控制系统通信服务器中的应用[J].微型电脑应用,2012,28(7):55-57.