?? ceudp.cpp
字號(hào):
// CEUDP.cpp: implementation of the CCEUDP class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "UDPDemo.h"
#include "CEUDP.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCEUDP::CCEUDP()
{
}
CCEUDP::~CCEUDP()
{
}
/******************************************************************************
函數(shù)介紹:打開(kāi)UDP通訊端口
入口參數(shù):pWnd: 指定父窗體指針
localPort: 指定遠(yuǎn)程UDP端口
romoteHost:指定遠(yuǎn)程IP地址
remotePort:指定遠(yuǎn)程UDP端口
出口參數(shù):(無(wú))
返 回 值:1代表成功;-1,-2,-3等都代表失敗
******************************************************************************/
DWORD CCEUDP::Open(CWnd* pWnd,int localPort,LPCTSTR remoteHost,int remotePort)
{
m_pOwnerWnd = pWnd;
// 加載winsock1.1動(dòng)態(tài)鏈接庫(kù)
WSADATA wsa;
if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)
{
return -1; // 代表失敗
}
// 創(chuàng)建UDP套接字
m_UDPSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (m_UDPSocket == INVALID_SOCKET)
{
return -2;
}
SOCKADDR_IN localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(localPort);
localAddr.sin_addr.s_addr = INADDR_ANY;
// 綁定地址
if(bind(m_UDPSocket,(sockaddr*)&localAddr,sizeof(localAddr))!=0)
{
return -3;
}
// 設(shè)置非堵塞通訊
DWORD ul= 1;
ioctlsocket(m_UDPSocket,FIONBIO,&ul);
// 創(chuàng)建一個(gè)線程退出事件
m_ExitThreadEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
// 創(chuàng)建通訊線程
AfxBeginThread(RecvThread,this);
m_RemoteAddr.sin_family = AF_INET;
m_RemoteAddr.sin_port = htons(remotePort);
// 此處要將雙字節(jié)轉(zhuǎn)換成單字節(jié)
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 1;
}
/******************************************************************************
函數(shù)介紹:關(guān)閉UDP通訊端口
入口參數(shù):(無(wú))
出口參數(shù):(無(wú))
返 回 值:1代表成功;-1,-2等都代表失敗
******************************************************************************/
DWORD CCEUDP::Close(void)
{
// 設(shè)置通訊線程退出事件,通知線程退出
SetEvent(m_ExitThreadEvent);
Sleep(2000);
// 關(guān)閉線程句柄
CloseHandle(m_ExitThreadEvent);
// 關(guān)閉socket
if (closesocket(m_UDPSocket) == SOCKET_ERROR)
{
return -1;
}
// 釋放socket資源
if (WSACleanup() == SOCKET_ERROR)
{
return -2;
}
return 1;
}
/******************************************************************************
函數(shù)介紹:發(fā)送數(shù)據(jù)
入口參數(shù):buf:緩沖區(qū)數(shù)據(jù)
len:緩沖數(shù)據(jù)長(zhǎng)度
出口參數(shù):(無(wú))
返 回 值:發(fā)送成功代表實(shí)際發(fā)送的字節(jié)數(shù),否則返回-1
******************************************************************************/
DWORD CCEUDP::SendData(const char *buf, int len)
{
int nBytes = 0;
int nSendBytes=0;
int nSumBytes =0;
int nErrorCode;
// 生成UDP數(shù)據(jù)包
UDPData sendData;
CopyMemory(sendData.FrameHead, FRAMEHEAD, 4);
sendData.DataPackageLen = len;
CopyMemory(sendData.FrameTail, FRAMETAIL, 4);
nSumBytes = len + 12;
char * sendBuf;
sendBuf = new char[nSumBytes];
CopyMemory(sendBuf, sendData.FrameHead, 4);
CopyMemory(sendBuf + 4, &(sendData.DataPackageLen), 4);
CopyMemory(sendBuf + 8, buf, len);
CopyMemory(sendBuf + 8 + len, sendData.FrameTail, 4);
// 發(fā)送數(shù)據(jù)
while (nSendBytes < nSumBytes)
{
nBytes = sendto(m_UDPSocket, sendBuf + nSendBytes, nSumBytes - nSendBytes, 0,
(sockaddr*)&m_RemoteAddr, sizeof(m_RemoteAddr));
if (nBytes == SOCKET_ERROR )
{
nErrorCode = WSAGetLastError();
m_OnUdpError(m_pOwnerWnd,nErrorCode);
return -1;
}
if (nSendBytes == nSumBytes)
{
break;
}
Sleep(1000);
nSendBytes = nSendBytes + nBytes;
}
delete[] sendBuf;
return nSendBytes;
}
/******************************************************************************
函數(shù)介紹:接收線程函數(shù)
入口參數(shù):lparam : 指?jìng)鬟M(jìn)線程的參數(shù)
出口參數(shù):(無(wú))
返 回 值:無(wú)意義。
******************************************************************************/
UINT CCEUDP::RecvThread(LPVOID lparam)
{
CCEUDP *pSocket;
pSocket = (CCEUDP*)lparam;
fd_set fdRead;
int ret;
TIMEVAL aTime;
char * recvBuf=NULL;
aTime.tv_sec = 1;
aTime.tv_usec = 0;
SOCKADDR_IN tmpAddr;
int tmpRecvLen;
int recvLen;
int iErrorCode;
char * recvedBuf = NULL;
int recvedBufLen;
while (TRUE)
{
// 收到退出事件,結(jié)束線程
if (WaitForSingleObject(pSocket->m_ExitThreadEvent,0) == WAIT_OBJECT_0)
{
break;
}
// 將set初始化空集合
FD_ZERO(&fdRead);
// 將pSocket->m_UDPSocket套接字添加到集合中
FD_SET(pSocket->m_UDPSocket, &fdRead);
// 調(diào)用select函數(shù),判斷套接字I/O狀態(tài)
ret = select(0, &fdRead, NULL, NULL, &aTime);
if (ret == SOCKET_ERROR)
{
iErrorCode = WSAGetLastError();
pSocket->m_OnUdpError(pSocket->m_pOwnerWnd, iErrorCode);
break;
}
if (ret > 0)
{
if (FD_ISSET(pSocket->m_UDPSocket, &fdRead))
{
tmpAddr.sin_family=AF_INET;
tmpAddr.sin_port = htons(pSocket->m_RemoteAddr.sin_port);
tmpAddr.sin_addr.s_addr =INADDR_ANY;
tmpRecvLen = sizeof(tmpAddr);
recvBuf = new char[512];
recvedBuf = new char[512];
ZeroMemory(recvBuf,512);
ZeroMemory(recvedBuf,512);
recvLen = recvfrom(pSocket->m_UDPSocket,recvBuf, 512,0,(SOCKADDR*)&tmpAddr,&tmpRecvLen);
if (recvLen == SOCKET_ERROR)
{
iErrorCode = WSAGetLastError();
pSocket->m_OnUdpError(pSocket->m_pOwnerWnd,iErrorCode);
break;
}
else if (recvLen == 0)
{
iErrorCode = WSAGetLastError();
pSocket->m_OnUdpError(pSocket->m_pOwnerWnd,iErrorCode);
break;
}
else
{
// 此處添加解析程序,將接收到的數(shù)據(jù)解析后,
if (pSocket->HandlePackage(recvBuf, recvLen, recvedBuf, recvedBufLen))
{
pSocket->m_OnUdpRecv(pSocket->m_pOwnerWnd, recvedBuf, recvedBufLen, (SOCKADDR*)&tmpAddr);
}
delete []recvBuf;
recvBuf = NULL;
delete []recvedBuf;
recvedBuf = NULL;
}
}
}
}
return 0;
}
/******************************************************************************
函數(shù)介紹:處理接收到的數(shù)據(jù)包
入口參數(shù):inBuf: 待處理的緩沖區(qū)
inBufLen:待處理的緩沖區(qū)長(zhǎng)度
出口參數(shù)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -