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();//具体处理客户请求
…
|