搭建Linux的组播环境(附Windows组播程序的代码)

项目需求需要在windows2008 r2的环境上搭建虚拟机Linux系统,并用Linux系统接收组播数据。在windows2008 r2搭建虚拟机,已经介绍过了。关键的地方在与,桥接网卡,静态IP要设置好。
组播是基于IP/TCP协议簇下的多播协议(Internet组管理协议),也叫IGMP协议。组播程序的代码与UDP网络编程的代码有些许变化。
Windows接收端代码
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include
#include"MdParser.h"
#pragma comment(lib, “ws2_32.lib”)

using namespace md_parser;

int main()
{
int iRet = 0;
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);

sockaddr_in addr;
addr.sin_family = AF_INET;
//addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_addr.S_un.S_addr = inet_addr("0.0.0.0");
addr.sin_port = htons(9411);

bool bOptval = true;
iRet = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptval, sizeof(bOptval));
if (iRet != 0) {
	printf("setsockopt fail:%d", WSAGetLastError());
	return -1;
}

iRet = bind(sock, (sockaddr*)&addr, sizeof(addr));
if (iRet != 0) {
	printf("bind fail:%d", WSAGetLastError());
	return -1;
}
printf("socket:%d bind success\n", sock);

// 加入组播  
ip_mreq multiCast;
//multiCast.imr_interface.S_un.S_addr = INADDR_ANY;
multiCast.imr_interface.S_un.S_addr = inet_addr("0.0.0.0");
multiCast.imr_multiaddr.S_un.S_addr = inet_addr("234.2.2.2");
iRet = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multiCast, sizeof(multiCast));
if (iRet != 0) {
	printf("setsockopt fail:%d", WSAGetLastError());
	return -1;
}

printf("udp group start\n");

int len = sizeof(sockaddr);
char strRecv[512] = { 0 };
while (true)
{
	memset(strRecv, 0, sizeof(strRecv));
	iRet = recvfrom(sock, strRecv, sizeof(strRecv) - 1, 0, (sockaddr*)&addr, &len);
	if (iRet <= 0) {
		printf("recvfrom fail:%d", WSAGetLastError());
		return -1;
	}
	printf("%s\n",strRecv);
	
}

closesocket(sock);

}

Windows发送端代码:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, “ws2_32.lib”)

int main()
{
int iRet = 0;
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);

sockaddr_in addr;
addr.sin_addr.S_un.S_addr = inet_addr("234.2.2.2");
addr.sin_family = AF_INET;
addr.sin_port = htons(9411);

char strSend[1024] = { 0 };
static int iIdx = 0;
while (1)
{
	sprintf_s(strSend, "udp send group data:%d", iIdx++);
	iRet = sendto(sock, strSend, strlen(strSend) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr));
	if (iRet <= 0) {
		printf("send fail:%d", WSAGetLastError());
	}
	else {
		printf("send data:%s\n", strSend);
	}
	Sleep(512);
}

closesocket(sock);
WSACleanup();

return 0;

}

在Windows环境下直接编译运行即可通过。但是在Linux系统无论是真实环境,还是虚拟机环境直接运行组播是接收不到数据的。需要抓包配置相应的网络环境,可以通过以下步骤检查网络环境。
1.检查Linux系统的防火墙是否关闭;
关闭防火墙的命令:
sudo systemctl stop firewalld 临时关闭
sudo systemctl disable firewalld ,然后reboot 永久关闭
sudo systemctl status firewalld 查看防火墙状态
查看防火墙是否关闭:
Systemctl status firewalld.service 若看到标注为active(running)则防火墙是开启状态。如果出现disactive(dead)的字样,说明防火墙已经关闭。
2.若关闭防火墙不能解决问题,则需要抓包,看一下路由转发的IGMP包的协议版本,将本地的IGMP包的协议版本改为路由器转发的一样即可。
3.最关键的一步是添加组播路由到本地的路由表中,在Windows系统下,这一步是由系统自动完成的,Linux好像需要自己配置。
添加路由命令:
route add -net 224.0.0.0 netmask 240.0.0.0 ens33(需要组播的网卡)
route add -net 0.0.0.0 netmask 0.0.0.0 ens33
4.将组播程序中的本地地址改为0.0.0.0即可

若在Linux环境下,可将网卡过滤规则设为0;具体命令如下:
cat “0” > /proc/sys/net/ipv4/conf/all/rp_filter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值