?? udp_ce.cpp
字號:
// UDP_CE.cpp: implementation of the CUDP_CE class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "UDPDemo.h"
#include "UDP_CE.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CUDP_CE::CUDP_CE()
{
}
CUDP_CE::~CUDP_CE()
{
}
/*
*函數介紹:打開UDP通訊端口
*入口參數:pWnd: 指定父窗體指針
localPort: 指定遠程UDP端口
romoteHost:指定遠程IP地址
remotePort:指定遠程UDP端口
*出口參數:(無)
*返回值:1代表成功;-1,-2,-3等都代表失敗
*/
DWORD CUDP_CE::Open(CWnd* pWnd,int localPort,LPCTSTR remoteHost,int remotePort)
{
WSADATA wsa;
m_pOwnerWnd = pWnd;
//加載winsock動態鏈接庫
if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)
{
return -1;//代表失敗
}
//創建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;
}
//設置非堵塞通訊
DWORD ul= 1;
ioctlsocket(m_UDPSocket,FIONBIO,&ul);
//創建一個線程退出事件
m_ExitThreadEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//創建通訊線程
AfxBeginThread(RecvThread,this);
m_RemoteAddr.sin_family = AF_INET;
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 1;
}
/*
*函數介紹:關閉UDP通訊端口
*入口參數:(無)
*出口參數:(無)
*返 回 值:1代表成功;-1,-2等都代表失敗
*/
DWORD CUDP_CE::Close(void)
{
//設置通訊線程退出事件,通知線程退出
SetEvent(m_ExitThreadEvent);
Sleep(2000);
//關閉線程句柄
CloseHandle(m_ExitThreadEvent);
//關閉socket
if (closesocket(m_UDPSocket) == SOCKET_ERROR)
{
return -1;
}
//釋放socket資源
if (WSACleanup() == SOCKET_ERROR)
{
return -2;
}
return 1;
}
/*
*函數介紹:發送數據
*入口參數:dataPriority: 數據優先級
dataType: 數據類型
buf:緩沖區數據
len:緩沖數據長度
*出口參數:(無)
*返回值:發送成功代表實際發送的字節數,否則返回-1
*/
DWORD CUDP_CE::SendData(const char *buf, int len)
{
int nBytes = 0;
int nSendBytes=0;
int nSumBytes =0;
int nErrorCode;
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);
//發送數據
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;
}
/*
*函數介紹:接收線程函數
*入口參數:lparam : 指傳進線程的參數
*出口參數:(無)
*返 回 值:無意義。
*/
UINT CUDP_CE::RecvThread(LPVOID lparam)
{
CUDP_CE *pSocket;
pSocket = (CUDP_CE*)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)
{
//收到退出事件,結束線程
if (WaitForSingleObject(pSocket->m_ExitThreadEvent,0) == WAIT_OBJECT_0)
{
break;
}
//將set初始化空集合
FD_ZERO(&fdRead);
//將pSocket->m_UDPSocket套接字添加到集合中
FD_SET(pSocket->m_UDPSocket,&fdRead);
//調用select函數,判斷套接字I/O狀態
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[1024];
recvedBuf = new char[1024];
ZeroMemory(recvBuf,1024);
ZeroMemory(recvedBuf,1024);
recvLen = recvfrom(pSocket->m_UDPSocket,recvBuf, 1024,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
{
//此處添加解析程序,將接收到的數據解析后,
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;
}
/*
*函數介紹:處理接收到的數據包
*入口參數:inBuf: 待處理的緩沖區
inBufLen:待處理的緩沖區長度
*出口參數:dataPriority:數據優先級
dataType:數據類型
outBuf:處理后的緩沖區數據
outBufLen:處理后的緩沖區數據長度
*返 回 值:合法則返回true,否則,返回false;
*/
bool CUDP_CE::HandlePackage(const char *inBuf,int inBufLen
,char *outBuf,int &outBufLen)
{
CString csBuf;
csBuf = inBuf;
int iPosHead = pos(FRAMEHEAD,inBuf,inBufLen);
int iPosTail = pos(FRAMETAIL,inBuf,inBufLen);
//沒有查到包頭或包尾
if ((iPosHead == -1) || (iPosTail == -1))
{
return FALSE;
}
//如果包頭位置大于等于包尾位置,就退出
if (iPosHead >= iPosTail)
{
return FALSE;
}
//得到數據包長度
int iPackLen;
CopyMemory(&iPackLen,inBuf+iPosHead+4,4);
//判斷包長度是否正確
if (iPackLen != iPosTail - iPosHead - 8)
{
return FALSE;
}
CopyMemory(outBuf,inBuf+8,iPackLen);
outBufLen = iPackLen;
return TRUE;
}
/*
*函數介紹:查找一個字符串的位置
*入口參數:aSubStr: 待查找的子串
aBuf:待查找的緩沖區
len:待查找的緩沖區長度
*出口參數:(無)
*返回值:找到的話,返回在父串中的位置,否則返回-1.
*/
int CUDP_CE::pos(LPCSTR aSubStr, const char *aBuf, int len)
{
bool aResult = TRUE;
int subLen = strlen(aSubStr);
for ( int i=0;i<len-subLen+1;i++)
{
aResult = TRUE;
for (int j=0;j<subLen;j++)
{
if (*(aBuf+i+j) != aSubStr[j])
{
aResult = FALSE;
break;
}
int k = 0;
}
if (aResult)
{
return i;
}
}
return -1;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -