UDP发送:
//成员变量定义
int m_nUdpPort; //自定义
SOCKET m_udpSocket;
sockaddr_in m_addrto;
//初始化广播Socket
m_udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (m_udpSocket != INVALID_SOCKET)
{
//启动SOCKET库,版本为2.0
WSADATA wsdata;
WSAStartup(MAKEWORD(2, 2), &(wsdata));
BOOL opt = TRUE;
setsockopt(m_udpSocket, SOL_SOCKET, SO_BROADCAST, (char* FAR)&opt, sizeof(opt));
m_addrto.sin_family = AF_INET;
m_addrto.sin_addr.s_addr = INADDR_BROADCAST;
m_addrto.sin_port = htons(m_nUdpPort);
}
发送数据:
//udp发送
CString strSendData = GetSendXml();
if (!strSendData.IsEmpty())
{
int nLenResult = 0;
int nOldBuffLen = 10;
BYTE* pBuffTemp = new BYTE[nOldBuffLen];
G_StringToASII(strSendData, pBuffTemp, nOldBuffLen, nLenResult);
sendto(m_udpSocket, (char *)pBuffTemp, nLenResult, 0, (sockaddr*)&m_addrto, sizeof(m_addrto));
}
这里用到一个函数G_StringToASII,这个函数是将CString字符串转换成ASII字符串,因为sendto函数的参数类型是char*类型,直接传入CString参数会乱码。
G_StringToASII函数如下所示:
BOOL G_StringToASII(CString const &strSrc, BYTE * &pRefStoreBuff, int &nBuffLen, int &nLenResult)
{
nLenResult = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, strSrc, -1, NULL, 0, NULL, NULL);
if (nLenResult > nBuffLen)
{
delete[] pRefStoreBuff;
pRefStoreBuff = new BYTE[nLenResult];
if (!pRefStoreBuff)
return FALSE;
nBuffLen = nLenResult;
}
memset((void*)pRefStoreBuff, 0, sizeof(char) * nBuffLen);
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, strSrc, -1, (LPSTR)pRefStoreBuff, nLenResult, NULL, NULL);
return TRUE;
}
UDP接收
//udp成员变量定义
SOCKET m_udpThreadReceiveSocket;
BOOL m_bExitUdpThread;
需要启动线程接收数据:
UINT recvUdpThread(LPVOID lParam)
{
CDlg *pDlg = (CDlg *)lParam;
int const BUFF_LEN = 1024;
char receiveBuff[BUFF_LEN] = { 0 };
int nDataLen = 0;
SOCKADDR_IN addrReceive;
SOCKADDR_IN addrCur;
int nSizeAddr = sizeof(addrCur);
int nUdpPort = 6020;//需要绑定的端口号
addrReceive.sin_family = AF_INET;
addrReceive.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrReceive.sin_port = htons(nUdpPort);
if ((pDlg ->m_udpThreadReceiveSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
return -1;
if (::bind(pDlg ->m_udpThreadReceiveSocket, (struct sockaddr *)&addrReceive, sizeof(addrReceive)) == SOCKET_ERROR)
return -1;
while (!pTouchDlg->m_bExitUdpThread)
{
nDataLen = recvfrom(pDlg ->m_udpThreadReceiveSocket, (char *)receiveBuff, BUFF_LEN, 0, (struct sockaddr *)&addrCur, &nSizeAddr);
if (nDataLen != ERROR)
{
CString strRev((char*)receiveBuff);
//去头尾,剩下XML
strRev = strRev.Mid(3, strRev.GetLength() - 6);
CString* pStr = new CString;
*pStr = strRev;
pTouchDlg->PostMessage(WM_RECEIVE_MSG_UDP, 0, (LPARAM)pStr);
//获取ip
// char str[INET_ADDRSTRLEN];
// inet_ntop(AF_INET, &addrCur.sin_addr, str, sizeof(str));
// CString strIp((char*)str);
}
}
return 0;
}
一定要记得,在程序退出时,关闭线程,关闭socket
//关闭udp接收
m_bExitUdpThread = TRUE;
closesocket(m_udpThreadReceiveSocket);
shutdown(m_udpThreadReceiveSocket, 0x00);
注意:线程中接收到的数据,一定要Post出去再进行处理,并且一定是PostMesage,不是SendMessage。