Я сделаю все возможное, чтобы оно было кратким.
Вопрос: что может быть причиной невозможности получения многоадресных пакетов в невиртуализированном коде (не JVM)
ОПЕРАЦИОННЫЕ СИСТЕМЫ:
Код ржавчины: (Не работает)
use std::net::UdpSocket;
fn main() {
let udp = UdpSocket::bind("[::]:0").expect("Unable to bind!");
println!("{}", udp.local_addr().unwrap());
udp.connect("ff02::fb%en0:5353").unwrap();
let mut buffer = [0; 65000];
let size = udp.recv(&mut buffer).unwrap();
println!("Data received: {}", size);
}
Код Kotlin (JVM): Работает
import java.net.DatagramPacket
import java.net.MulticastSocket
fun main() {
val port = 5353 // Multicast port
val socket = MulticastSocket(port)
val buffer = ByteArray(1024)
val packet = DatagramPacket(buffer, buffer.size)
println("UDP server listening for multicast packets on ${socket.localSocketAddress}")
while (true) {
socket.receive(packet)
val receivedData = packet.data.copyOf(packet.length)
val receivedMessage = String(receivedData)
println("Received message: $receivedMessage")
}
}
Код C: (Не работает)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAX_LEN 1024 // Maximum message length
int main() {
int sockfd;
struct sockaddr_in addr;
struct ip_mreq mreq;
char buffer[MAX_LEN + 1];
int bytes_received;
// Create a UDP socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
// Fill in the address structure
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any interface
addr.sin_port = htons(12345); // Choose any port number you like
// Bind the socket to the address
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// Specify the multicast group to join
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.251"); // Multicast group address
mreq.imr_interface.s_addr = htonl(INADDR_ANY); // Listen on any interface
// Join the multicast group
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
// Receive multicast messages
while (1) {
bytes_received = recvfrom(sockfd, buffer, MAX_LEN, 0, NULL, NULL);
if (bytes_received < 0) {
perror("recvfrom failed");
exit(EXIT_FAILURE);
}
buffer[bytes_received] = '\0'; // Null-terminate the received data
printf("Received message: %s\n", buffer);
}
// Close the socket
close(sockfd);
return 0;
}
Да, сэр, он предоставляет информацию для маршрутизации на хост (я предполагаю, что это зависит от платформы, поскольку это было разрешено только на MacOS - также проверено с помощью netcat).
Согласно RFC, идентификатор зоны %en0 действителен только для адресации IPv6 Link-Local (fe80::/10). «Чтобы ограничить этот риск, реализации НЕ ДОЛЖНЫ разрешать использование этого формата, за исключением четко определенных случаев использования, таких как отправка на локальные адреса с префиксом fe80::/10. На момент написания это единственный четко определенный формат. использование известно».
Интересно... Есть идеи, в чем может быть причина, по которой я не могу слушать mDNS с помощью Rust и C?
версия c выше получает пакеты ipv4 в присоединенной группе, насчет ржавчины и Java - понятия не имею, что код на разных языках не равен
@ yvs2014 yvs2014 на какой ОС вы это тестируете? На моем MacOS код C не получает никаких пакетов.
в Linux: отправка чего-то многоадресного на записанный ipv4addr:port и получение этого
Другое дело, что и как вы это проверяете
Что ж, я сравниваю это с тем, что вижу другой трафик на Wireshark, отправленный другими устройствами (Spotify, Homepods и тому подобное), но ни одно из них не поступает в программу с приведенным выше кодом (кроме Kotlin).
«Другой трафик» — это слишком расплывчато. В примерах на Rust и Kotlin я даже не вижу присоединения к мультикаст-группе, вы думаете, что там сделано неявно?
Давайте продолжим обсуждение в чате.





Я ответил на аналогичный вопрос (также опубликованный мной, пытаясь прояснить ситуацию): mDNS / Bonjour / UDP 5353 Повторное использование портов
Является ли
%en0в адресе, данном РастуUdpSocket::connect, намеренным? Я не думаю, что это действительно так.