3.2    Web服务端
Web服务器端需要完成与硬件的接口、解析客户端指令、发送数据到客户端等功能。系统在实现过程中,对遇到的以下问题进行分析解决。 
(1) 多用户并发访问
系统是B/S模式,需要处理多用户的并发访问。一般TCP/IP服务器通信软件都是并发型的,即由一个守护线程负责监听客户机的连接请求,当请求发生时创建新线程与客户机建立连接以完成通信,其缺点是随着连接的客户机数量的增多,生成的通信线程数量会相应增多,在客户机数量较多的应用场合势必影响服务器的运行效率。本系统使用“I/O完成端口”处理并发请求。I/O 完成端口是这样一种机制:应用程序在启动时会首先创建一个线程池,然后该应用程序使用线程池处理异步I/O请求。线程池收到请求后,交给线程池里的线程具体处理I/O请求。对于需要处理大量并发异步I/O请求的应用程序来说(相比于在I/O请求发生时创建线程),使用完成端口,可以做得更快且更有效率。 
利用IO完成端口主要相关函数代码: 
m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); //建立m_nThreadIo工作线程池 
for(i=0; i<m_nThreadIo; i++){ //m_nThreadIo=5 
_beginthread(ThreadIoWorker, 0, (LPVOID)this); 
}  
ThreadIoWorker为工作线程函数,客户请求送到此函数 
void  ThreadIoWorker(LPVOID pParam){ 
… 
CIOCP * pThis = (CIOCP*)pParam; 
hCompletionPort= pThis -> m_hJobCompletionPort; 
while(1){ 
…//获取完成端口事件 
bIORet = GetQueuedCompletionStatus( 
hCompletionPort,&dwIoSize, 
(LPDWORD) (&lpIoContext),  
&lpOverlapped, INFINITE); 
if(bIORet && lpIoContext!=NULL) 
    {           pOverlapBuff=CONTAINING_RECORD(lpOverlapped, CIoBuffer, m_ol); 
        pOverlapBuff->SetIoSize(dwIoSize);          lpIoContext->ProcessIoMsg(pOverlapBuff);  
//将请求放入到完成端口的线程池进行处理。 
    } 
… 
放入线程池的时候可以使用临界对象,实现线程同步,主要流程: 
EnterCriticalSection(&m_csJob); 
m_dqJobs.push_back(Job); 
LeaveCriticalSection(&m_csJob); 
PostQueuedCompletionStatus(m_hCompletionPort, 0, 1, NULL);//唤醒线程池中的一个等待线程进行处理 
线程池中的处理线程关键过程如下: 
void ThreadJob(LPVOID pParam) 
{    CIOCP * pThis = (CIOCP*)pParam; 
    while(1) 
    {   bIORet = GetQueuedCompletionStatus( 
         hCompletionPort,&dwIoSize, 
         &dwKey, &lpOverlapped, INFINITE); 
         pThis->ProcessJob();//具体处理客户请求 
…  			
				 |