layout: post
title: “Windows多网卡环境接收组播包”
subtitle: “跨过千山万水,踏遍海角天涯–I got it!”
date: “2018-01-14”
author: “cj”
tags:
multicast
windows
multiple-interfaces
c++
说明:本文仅针对IPv4
局域网发现技术有很多,常用组播(或称为多播):一台设备发送组播包,其他设备加入组播组,接收到组播包时即可知晓发送端IP,接收端回应约定数据即可让发送端也得知这些接收端的IP。
组播地址与端口号
IPv4的D类地址(224.0.0.0至239.255.255.255)是IPv4多播地址。D类地址的低28位构成多播组ID(group ID),整个32位地址则成为组地址(group address)。
224.0.0.1为all-hosts组,224.0.0.2是all-routers组。
224.0.0.0~224.0.0.255之间的地址(224.0.0.0/24)称为链路局部(link-local)多播地址,是为低级拓扑发现和维护协议保留。
一般应用程序使用239.0.0.0~239.255.255.255之间的地址,称作可管理地划分范围的IPv4多播空间(administratively scoped IPv4 multicast space)(RFC2365)。
本文使用239.254.43.21:45454作为组播地址和端口号
static const auto MULTICAST_GROUP_ADDRESS = "239.255.43.21";
static const unsigned short MULTICAST_GROUP_PORT = 45454;
static const auto LOCAL_IP = "192.168.1.222";
WinSock2编程须知
winsock.h与winsock2.h的一些宏定义如IP_ADD_MEMBERSHIP
使用了不同的值,因此须特别注意。这破问题我是在join gruop(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP...)
)始终失败,后来检查错误码为10042 (WSAENOPROTOOPT),搜索得知不可直接#include <windows.h>
, 而需要
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
具体可参考INFO: Header and Library Requirement When Set/Get Socket Options at the IPPROTO_IP Level
发送端
单网卡环境
无需多提,仅需创建UDP socket,将数据报发送至D类地址的某个约定好的端口即可。
struct sockaddr_in addr = {
};
addr.sin_family = AF_INET;
addr.sin_port = htons(MULTICAST_GROUP_PORT);
addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP_ADDRESS);
int addr_len = sizeof(addr);
char host[1024] = {
0 };
gethostname(host, 1024);
int msgNo = 0;
char msg[1024] = {
0 };
while (true) {
sprintf(msg, "Groupcast Message %s No.%d", host, msgNo++);
int ret = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&addr, addr_len);
if (ret < 0) {
perror("sendto");
return -