【发布时间】:2022-01-16 11:41:50
【问题描述】:
我正在尝试创建一个应用程序,它使用多播与本地网络上的应用程序的其他实例通信(应用程序应该在 windows 和 linux 下工作)。
我是多播的新手,所以我尝试使用我在互联网上找到的以下代码:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define EXAMPLE_PORT 6000
#define EXAMPLE_GROUP "239.124.0.1"
// If argc == 0, recieve, else send
int main(int argc, char**argv)
{
struct sockaddr_in addr;
socklen_t addrlen = 0;
int sock = 0, cnt = 0;
struct ip_mreq mreq;
char message[50];
/* set up socket */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
bzero((char *)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(EXAMPLE_PORT);
addrlen = sizeof(addr);
if (argc > 1) {
/* send */
addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP);
while (1) {
time_t t = time(0);
sprintf(message, "time is %-24.24s", ctime(&t));
printf("sending: %s\n", message);
cnt = sendto(sock, message, sizeof(message), 0,
(struct sockaddr *) &addr, addrlen);
if (cnt < 0) {
perror("sendto");
exit(1);
}
sleep(5);
}
} else {
/* receive */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
perror("setsockopt mreq");
exit(1);
}
while (1) {
cnt = recvfrom(sock, message, sizeof(message), 0,
(struct sockaddr *) &addr, &addrlen);
if (cnt < 0) {
perror("recvfrom");
exit(1);
} else if (cnt == 0) {
break;
}
printf("%s: message = \"%s\"\n", inet_ntoa(addr.sin_addr), message);
}
}
}
代码成功发送了我可以在我的安卓手机上接收到的多播数据包(通过编译完全相同的代码并使用 Termux 编译/执行)。
所以我知道代码正在运行。 但这是我的问题:在 linux 和 windows 上,我无法接收数据包。我可以发送它们(我的手机确实收到了来自两者的数据包),但我无法接收。
令我惊讶的是,它在我的 linux 和 android 上是完全相同的代码(在 windows 上,使用 winsock2 的代码只有一些调整)。
此外,我可以看到我的 linux 确实收到数据包:
$ sudo tcpdump -i wlp58s0 host 239.124.0.1
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wlp58s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:36:59.196616 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
12:37:04.112507 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
12:37:09.129963 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel
192.168.1.10 是我在该网络上的手机 IP 地址。
我也可以看到我成功加入了组播组:
$ netstat -gn | grep 239.124.0.1
wlp58s0 1 239.124.0.1
所以我的问题是为什么我不能在 linux/windows 上接收多播数据包?
我需要更改哪些代码才能接收它们?
编辑:
看来如果我禁用我的防火墙sudo systemctl stop firewalld.service 我可以收到数据包。
我真的不想让我的用户禁用他们的防火墙,我该怎么做? (为什么防火墙首先会阻止多播?)
【问题讨论】:
标签: c linux windows sockets multicast