上一篇文章我详细介绍了如何开发一款高性能的TCP服务器的网络传输层.本章我将谈谈如何开发一个高性能的UDP服务器的网络层.UDP服务器的网络层开 发相对与TCP服务器来说要容易和简单的多,UDP服务器的大致流程为创建一个socket然后将其绑定到完成端口上并投递一定数量的recv操作.当有 数据到来时从完成队列中取出数据发送到接收队列中即可。
测试结果如下:
WindowsXP Professional,Intel Core Duo E4600 双核2.4G , 2G内存。同时30K个用户和该UDP服务器进行交互其CPU使用率为10%左右,内存占用7M左右。
下面详细介绍该服务器的架构及流程:
1. 首先介绍服务器的接收和发送缓存UDP_CONTEXT。

friend
IP_ADDR m_RemoteAddr; 
HEAP_SIZE
MAX_IDL_DATA
}
UDP_CONTEXT()


}UDP_CONTEXT的实现流程和TCP_CONTEXT的实现流程大致相同,此处就不进行详细介绍。
2. UDP_RCV_DATA,当服务器收到客户端发来的数据时会将数据以UDP_RCV_DATA的形式放入到数据接收队列中,其声明如下:

friend
CHAR


UDP_RCV_DATA(


RCV_HEAP_SIZE 

}


UDP_RCV_DATA的实现和TCP_RCV_DATA大致相同, 此处不在详细介绍.
下面将主要介绍UdpSer类, 该类主要用来管理UDP服务.其定义如下:

UdpSer();

* Desc : 初始化静态资源,在申请UDP实例对象之前应先调用该函数, 否则程序无法正常运行
***********************************************************************

* Desc : 在释放UDP实例以后, 掉用该函数释放相关静态资源
***********************************************************************







* Name : CloseServer()
* Desc : 关闭服务器
***************************************************

SOCKET m_hSock;
vector



HANDLE 


* Name : WorkThread()
* Desc : I/O 后台管理线程
***************************************************
}
1. InitReource() 主要对相关的静态资源进行初始化.其实大致和TcpServer::InitReource()大致相同.在UdpSer实例使用之前必须调用该函数进行静态资源的初始化, 否则服务器无法正常使用.
2.ReleaseReource() 主要对相关静态资源进行释放.只有在应用程序结束时才能调用该函数进行静态资源的释放.
3. StartServer()
该函数的主要功能启动一个UDP服务.其大致流程为先创建服务器UDP socket, 将其绑定到完成端口上然后投递一定数量的recv操作以接收客户端的数据.其实现如下:

BOOL bRet
WSABUF RcvBuf
DWORD dwBytes
DWORD dwFlag
INT nAddrLen
INT iErrCode 
THROW_LINE;
}
m_bSerRun
m_hSock
THROW_LINE;
}
ULONG ul
ioctlsocket(m_hSock, FIONBIO, 

setsockopt(m_hSock, SOL_SOCKET, SO_REUSEADDR, (

setsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
setsockopt(m_hSock, SOL_SOCKET, SO_RCVBUF, (CHAR
IP_ADDR addr(szIp, nPort);
closesocket(m_hSock);
THROW_LINE;
}



UDP_CONTEXT
dwFlag
dwBytes
nAddrLen
RcvBuf.buf
RcvBuf.len 
pRcvContext
pRcvContext
iErrCode
,
delete pRcvContext;
pRcvContext
}
}
delete pRcvContext;
}
}
}
bRet
_TRACE(
}
}4. GetRcvData(), 从接收队列中取出一个数据包.

UDP_RCV_DATA
EnterCriticalSection(
vector
pRcvData
m_RcvDataQue.erase(iterRcv);
}
}
LeaveCriticalSection(
}
5. SendData() 发送指定长度的数据包.

BOOL bRet
THROW_LINE;
}
UDP_CONTEXT
pSendContext
pSendContext
memcpy(pSendContext
WSABUF SendBuf
DWORD dwBytes
SendBuf.buf
SendBuf.len 
INT iErrCode
delete pSendContext;
THROW_LINE;
}
}
delete pSendContext;
THROW_LINE;
}
}
bRet
_TRACE(
}
}
6. CloseServer() 关闭服务

m_bSerRun
closesocket(m_hSock);
}
7. WorkThread() 在完成端口上工作的后台线程

UdpSer
DWORD dwTrans
LPOVERLAPPED pOl
UDP_CONTEXT 
BOOL bOk 
pContext
pThis
delete pContext;
pContext
}
}
}
}
}
8.ReadCompletion(), 接收操作完成后的回调函数

UDP_CONTEXT
WSABUF RcvBuf
DWORD dwBytes
DWORD dwFlag
INT nAddrLen
INT iErrCode 
#ifdef _XML_NET_
EnterCriticalSection(
UDP_RCV_DATA
m_RcvDataQue.push_back(pRcvData);
}
delete pRcvData;
}
LeaveCriticalSection(
EnterCriticalSection(
UDP_RCV_DATA
m_RcvDataQue.push_back(pRcvData);
}
delete pRcvData;
}
LeaveCriticalSection(
}


RcvBuf.len 
iErrCode
,
ATLTRACE(
, __FILE__, __LINE__, dwNumberOfBytesTransfered, WSAGetLastError());
delete pRcvContext;
pRcvContext
}
}
delete pRcvContext;
}
}
本文详细介绍了一种高性能UDP服务器的设计思路与实现流程。该服务器利用完成端口进行高效的I/O操作,通过合理的缓存管理和线程调度实现了良好的并发性能。

1235

被折叠的 条评论
为什么被折叠?



