用时,将首先调用0pen方法打开UDP通讯端口,然后调用SendData方法发送数据,同时还 可以调用m 回调函数来接收数据,当使用完成时,再调用 方法关闭.OnUdpRecv Close UDP
通讯端口。这3个方法的声明如下: public:
//打开UDP通讯
DWORD Open(void★pOwner,int localPort,LPCTSTR remoteHost ,int remotePort)j //关闭UDP通讯 DWORD Close(void); //发送数据
DWORD SendData(const char+buf,int len);
Open、Close和SendData方法的实现如程序清单l 2.3所示。 /““““““+++++++++++****程序清单l2-3\ ≯
*函数介绍:打开UDP通讯端口
+入口参数:pOwner:指定父对象指针 localPort:指定远程UDP端口 romoteHost:指定远程IP地址 remotePort:指定远程UDP端口 *出口参数:(无)
*返回值:l代表成功;一l、一2、一3等都代表失败 ★j DWORD CUDP—CE::0pen(void+pOwner,int localPort,LPCTSTR remoteHost,int remotePort) {
WSADATA WSa;
//传递父对象指针 m_pOwner=pOwner;
//加载winsock动态链接库
if(WSAStartup(MAKEWORD(2,2),&wsa)!-0) f
return一1;//代表失败 )
//创建UDP套接字
m—UDPSocket。socket(AF—INET,SOCK_DGRAM,IPPROT0—UDP)j if(m—UDPSocket==INVALI吐SOCKET) {
return-2; }
//设置本地地址
SOCKADDR——IN localAddr;
localAddr.sin—family=AF_INET;
localAddr.sin_port=htons(10calPort)j
localAddr-sin—addr.s—addr=INADDR—ANY; //绑定地址
if(bind(m_UDPSocket,(sockaddr+)&localAddr,sizeof(10calAddr))!-0) {
return一3; )
//设置非堵塞通讯 DWORD ul=1j
ioctlsocket(m—UDPSocket,FIONBl0,&u1); //创建一个线程退出事件
m—ExitThreadEvent =CreateEvent(NULL t TRUE f FALSE f NULL); //创建通讯线程
AfxBeginThread(RecvThread,this); //设置对方地址
m RemoteAddr.Sin family=AF INETj
m RemoteAddr.Sin port=htons(remotePort); //此处要将双字节转换成单字节 char anSiRemoteHost[255];
ZeroMemory(ansiRemoteHoSt,255);
WideCharToMultiByte(CP ACP,WC COMPOSITECHECK,remoteHost,wcslen(remoteHost) ,ansiRemoteHost,WCSlen(remoteHost),NULL,NULL); m RemoteAddr.sin addr.s addr=inet addr(ansiRemoteHost); return l; |+
*函数介绍:关闭UDP通讯端口 *入口参数:(无) *出口参数:(无)
+返回值:l代表成功;一l、一2等都代表失败 ★f
DWORD CUDP—CE::Close(void) (
//设置通讯线程退出事件,通知线程退出 SetEvent(m—ExitThreadEvent); Sleep(1000); //关闭线程旬柄
CloseHandle(m ExitThreadEvent)j //关闭socket
if(closesocket(m UDPSocket)==SOCKET—ERROR) {
return一1; )
//释放socket资源
if(WSACleanup()==SOCKET—ERROR) {
return一2; }
return l; ”
*函数介绍: *入口参数: 发送数据
buf:缓冲区数据 酱糊圈圈—■■■■
第12章UDP编程 427
Len:缓冲数据长度 *出口参数:(无)
+返回值:发送成功代表实际发送的字节数,否则返回一l ★f
DWORD CUDP—CE::SendData(const char+buf,int len) {
int nBytes=0;//每次发送出去的字节
int nSendBytes=O j //已经发送出去的字节 int nErrorCode=0;//错误码 //发送数据
while(nSendBytes //发送数据 nBytes=sendto(m_UDPSocket,buf+nSendBytes,len—nSendBytes,0, (sockaddr+)&m RemoteAddr,Sizeof(m RemoteAddr)); if(nBytes==SOCKET—ERROR) { nErrorCode=WSAGetLastError()j i f(m_OnUdpError) { m_OnUdpError(m_pOwner,nErrorCode); ) retUrn一1; //全部发送完毕 if(nSendBytes==len) { break; } //循环发送 Sleep(500); nSendBytes=nSendBytes+nBytes; ) return nSendBytes; ) /★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★+★★★★+++★★+★+★★/ 5)为CUDP CE类添加接收数据线程函数RecvThread,该线程在UDP打开后就开始运 行,到关闭UDP后退出。RecvThread线程函数用于实时检测是否有UDP数据到达,实现实 时异步数据读取。该线程函数定义如下: private: //通讯线程函数 StatiC UINT RecvThread(LPVOID RecvThread函数的具体实现如程序清单 iparam); 12.4所示。

