UDP发送与接收

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013183287/article/details/85596494

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。

猜你喜欢

转载自blog.csdn.net/u013183287/article/details/85596494