windows 实现UDP广播获取设备

关键逻辑

1、获取本机所有IP,把IP的最后一个字段值改为255,去掉重复的IP

2、遍历所有IP进行广播

代码实现

// BroadcastDemo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include   
#include   
#include   
#include 
#pragma comment(lib, "ws2_32.lib")

#include 
#include 
#include 
using namespace std;





// 解析接收内容
bool ParseRecvData(const vector& vctRecvData, string& strIp, int& iTcpPort, string& strTypeName)
{
	if (vctRecvData.size() < 35)
	{
		return false;
	}

	char szTemp[512] = { 0 };
	std::string szModelName;
	szModelName.assign(vctRecvData.begin(), vctRecvData.begin() + 10);
	int iPos = szModelName.find_last_not_of(' ');//去掉尾部空格
	szModelName = szModelName.substr(0,iPos + 1);

	strTypeName = szModelName;

	sprintf(szTemp, "%d.%d.%d.%d", *(vctRecvData.begin() + 18), *(vctRecvData.begin() + 19), *(vctRecvData.begin() + 20), *(vctRecvData.begin() + 21));
	std::string IPAddress(szTemp);

	int iPort = (*(vctRecvData.begin() + 32) << 8) + *(vctRecvData.begin() + 33);
	sprintf(szTemp, "%d", iPort);
	std::string PortNumber(szTemp);

	return true;
}

// 获取广播地址
bool GetBroadcastAddrs(set& lstIP)
{
	// 临时保存IP
	char szHostName[256] = {0};
	gethostname(szHostName, sizeof(szHostName));
	struct hostent* pHost = gethostbyname(szHostName);
	if (pHost == NULL)
	{
		return false;
	}

	in_addr addr;
	for (int i = 0; pHost->h_addr_list[i] != NULL; i++)
	{
		memcpy(&addr, pHost->h_addr_list[i], sizeof(in_addr));
		string strIp = inet_ntoa(addr);
		// 最后一个值转成255
		string strBroadcastIp = strIp.substr(0, strIp.find_last_of('.')) + ".255";
		lstIP.insert(strBroadcastIp);
	}

	return true;
}


int main(int argc, char*argv[]) 
{ 
	WSADATA wsaData;
	WORD sockVersion = MAKEWORD(2,2); 
	if (WSAStartup(sockVersion, &wsaData)) //调用Windows Sockets DLL
	{ 
		printf("Winsock无法初始化!\n");
		WSACleanup();
		return 0;
	}

	set vctIpList;
	if (!GetBroadcastAddrs(vctIpList))
	{
		return 0;
	}

	int iSocket = 0; 
	struct sockaddr_in mcast_addr; 
	iSocket = socket(AF_INET, SOCK_DGRAM, 0);
	if (iSocket == -1) 
	{ 
		closesocket(iSocket);
		WSACleanup();
		return -1; 
	} 

	memset(&mcast_addr, 0, sizeof(mcast_addr));					/*初始化IP多播地址为0*/ 
	mcast_addr.sin_family = AF_INET;							/*设置协议族类行为AF*/ 
	mcast_addr.sin_addr.s_addr = inet_addr("192.168.199.255");	/*设置多播IP地址*/ 
	mcast_addr.sin_port = htons(1860);					/*设置多播端口*/ 

	/*向多播地址发送数据*/ 
	string strSendData = "FIND\r";
	int iRet = sendto(iSocket, strSendData.c_str(), strSendData.length(), 0, (struct sockaddr*)&mcast_addr, sizeof(mcast_addr)) ; 
	if( iRet < 0) 
	{ 
		closesocket(iSocket);
		WSACleanup();
		return -2; 
	} 

	DWORD dwTime = GetTickCount();
	while( (GetTickCount() - dwTime) < 6000)
	{
		// 设置接收超时时间为2秒
		int iTimeOut = 2000;
		iRet = setsockopt(iSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeOut, sizeof(int));
		if (iRet < 0)
		{
			closesocket(iSocket);
			WSACleanup();
			break;
		}

		int times = 0; 
		int addr_len = 0; 
		const int iBufSize = 256;
		char buff[iBufSize] = { 0 }; 
		addr_len = sizeof(mcast_addr); 
		memset(buff, 0, iBufSize); /*清空接收缓冲区*/ 
		// 接收数据 
		iRet = recvfrom(iSocket, buff, iBufSize, 0,(struct sockaddr*)&mcast_addr, &addr_len); 
		if( iRet == -1) 
		{ 
			closesocket(iSocket);
			WSACleanup();
			break;
		} 
		/*打印信息*/ 
		printf("Recv %dst message from server:%s\n", times, buff); 
		//vector vctData;
		//string strIp;
		//int iTcpPort;
		//string strTypeName;

		//for (int i = 0; i < iBufSize; i++)
		//{
		//	vctData.push_back((unsigned char)buff[i]);
		//}

		//ParseRecvData(vctData, strIp, iTcpPort, strTypeName);	
	}

	closesocket(iSocket);
	WSACleanup();

	system("pause");

	return 0; 
}


 

你可能感兴趣的:(C++)