1

我有一台 iPad,它不会“看到”网络上的 bonjour 设备。所以我想发送一个 UDP MDNS 数据包,以便网络为 IP 提供网络上最新的设备,以便我可以在 iPad 上执行镜像。我能够创建一个套接字,但我发送的数据不正确。有任何想法吗?

struct icmphdr
    {
        u_int16_t qr;       /* type sub-code */
        u_int16_t opcode;
        u_int16_t aa;
        u_int16_t tc;
        u_int16_t rd;
        u_int16_t ra;
        u_int16_t z;
        u_int16_t ad;
        u_int16_t cd;
        u_int16_t rcode;
        u_int16_t q_count;
}
// Create the socket connection
    int sd = socket(AF_INET, SOCK_DGRAM, 0);

// Configure the port and ip we want to send to
    struct sockaddr_in broadcastAddr; // Make an endpoint
    memset(&broadcastAddr, 0, sizeof (broadcastAddr));
    broadcastAddr.sin_family = AF_INET;
    broadcastAddr.sin_len = sizeof(broadcastAddr);
    broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    broadcastAddr.sin_addr.s_addr = inet_addr("224.0.0.251");
    broadcastAddr.sin_port = htons(5353); // Set port 5353

    bind (sd, (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr));
    struct icmphdr req;
    req.qr=00;      // Reponse: Message is query
    req.opcode=00;  // Opcode: Standard Query (0)
    req.tc=00;      // Truncated: Message is not truncated
    req.rd=00;      // Recursion desired: Don't do query recursively
    req.z=00;       // Z: reserved (0)

    req.ad=00;      // Non-authenticated data: Unacceptable
    req.ra=02;      // Questions: 2
    req.cd = 00;
    req.rcode = 00;
    req.q_count = 00;
    req.aa = 00;

    if (sendto(sd, &req, sizeof(req), 00, (struct sockaddr*)&broadcastAddr, sizeof broadcastAddr)) {
        NSLog(@"%s",strerror(errno));
    }
    close(sd);
4

1 回答 1

1

首先 - 你怎么知道你的 iPad 没有看到 Bonjour 设备?除非它在非常早期的 iO​​S 版本上,否则应该可以。

第二 - Bonjour 查询(通常)通过对 PTR 记录的 DNS 请求完成,而不是 ICMP。AFAIK 无法获取网络上每个Bonjour 设备的列表。因此,您可以询问您感兴趣的服务,或查询 _services._dns-sd._udp.local 以获得服务列表,然后查询其中的每一个。

无论哪种方式,您的数据包都需要一些问题信息。google 了解 DNS 数据包结构,这是 PTR 请求的快速指南——

id - 2 个字节,始终为零 flags - 2 个字节,请求问题计数为零 - 2 个字节,在这种情况下 1 个答案计数 - 2 个字节,零权限计数 - 2 个字节,零附加计数 - 2 个字节,零

接下来是您的问题 - 名称(例如 _airport._tcp.local) - 采用 3www6google3com0 格式类型 - 2 个字节,PTR 类型类 12 个 - 2 个字节,互联网类 1 个

应该这样做。

但是请注意,在你遇到这个麻烦之前,看看你是否可以 bind() 到端口 5353。它不会让我这样做,说地址正在使用中。我想那些将 MDNS 响应程序移植到 iOS 的人忘记在他们的套接字上设置“重用地址”选项。就这样结束了。多谢你们。

于 2014-08-12T23:09:41.343 回答