c++组播基本实现

组播详解及示例代码

组播:用于对一组特定的主机进行通信,且这个特定的组内主机可以动态添加和删除多台主机,组内所有主机收到相同一份数据副本

组播地址

组播依赖于D类地址,范围从224.0.0.0到239.255.255.255。

224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;

224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;

224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;

239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。

组播属性设置
属性说明
IP_ADD_MEMBERSHIP加入指定的组播
IP_DROP_MEMBERSHIP退出指定的组播
IP_MULTICAST_IF设置组播中发送数据报文的接口
IP_MULTICAST_TTL设置组播中数据报文的生存时间(TTL),默认为1
IP_MULTICAST_LOOP设置组播中数据报文的副本是否回传
组播Demo
发送端
  1. 创建udpsocket
  2. 设置组播地址
  3. 发送数据
void muticast_sender()
{
	const char* GROUP_IP = "239.0.0.1";
	const int GROUP_PORT = 23888;
	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
	
	//设置组播地址
	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = inet_addr(GROUP_IP);
	addr.sin_port = htons(GROUP_PORT);

	while (true)
	{
		std::string msg = "muticast mesage";
		if (sendto(sock, msg.c_str(), msg.size(), 0, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
		{
			std::cout << "muticast message failed" << std::endl;
			break;
		}
		std::cout << "send muticast message ok" << std::endl;
		std::this_thread::sleep_for(std::chrono::milliseconds(5000));
	}
}
组播数据接收到
  1. 创建udpsocket
  2. 绑定组播端口 bind
  3. 设置组播属性,eg:IP_MULTICAST_LOOP ,IP_MULTICAST_TTL
  4. 加入组播
  5. 接收数据
void muticast_recever()
{
	const char* GROUP_IP = "239.0.0.1";
	const int GROUP_PORT = 23888;
	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

	//绑定组播端口
	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	addr.sin_port = htons(GROUP_PORT);

	
	int nret = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
	if (SOCKET_ERROR == nret)
	{
		std::cout << "Failed to bind socket" << std::endl;
		return;
	}

	int loop = 1;
	if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loop, sizeof(loop)) == -1)
	{
		std::cout << "Failed to setsockopt: IP_MULTICAST_LOOP" << std::endl;
		return;
	}

	//多网卡,加入组播
	for (auto& adapter_item:vec_adapter)
	{
		struct ip_mreq mreq;
				mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP);
				//::inet_pton()
				inet_pton(AF_INET, adapter_item.ip.c_str(), &mreq.imr_interface.s_addr);
				//mreq.imr_interface.s_addr = htonl(INADDR_ANY);
				if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == SOCKET_ERROR)
				{
					DWORD dwErrcode = WSAGetLastError();
					XLOGE("[%s]Failed to join multicast group,errcode:%d", adapter_item.ip.c_str(),dwErrcode);
				}
				else
				{
					XLOGI("[%s]join multicast group", adapter_item.ip.c_str());
				}
	}
	
	// 接收消息
	while (true)
	{
		char buffer[1024];
		struct sockaddr_in senderAddr;
		int senderAddrLen = sizeof(senderAddr);
		int numBytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&senderAddr, &senderAddrLen);
		if (numBytes == SOCKET_ERROR) {
			std::cerr << "Failed to receive message" << std::endl;
			return;
		}

		buffer[numBytes] = '\0';
		std::cout << "Received message from " << inet_ntoa(senderAddr.sin_addr) << ": " << buffer << std::endl;
	}
}
问题1:加入组播的时候遇见错误10042?

库导致的,取消ws2_32.lib,引入wsock32.lib,问题解决。
参考博客:https://blog.csdn.net/wmx313880747/article/details/39930049

问题2:多网卡?

需要加所有的网卡ip都加入组播
参考博客: https://blog.csdn.net/u012134942/article/details/109231666?spm=1001.2014.3001.5506

####问题排查

Windows 查看网卡是否加入多播组
netsh interface ipv4 show joins查看绑定关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值