.net framework4.8通过Makaretu.Dns.Multicast启用mDNS服务进行多播查询并且目标主机单播响应

Makaretu.Dns.Multicast版本0.27.0.0

想用winform做一个mDNS服务的组播功能,由于目标主机知道来源主机的ip地址,想着让目标主机直接点对点给源主机发送udp数据包

组播IP:224.0.0.251,端口:5353,返回方式为QU(规定目标主机的返回方式为单播,QM:表示组播)。

1.首先nuget安装Makaretu.Dns.Multicast

 

2.直接上代码,因为我用的是QU查询,因此要调用SendUnicastQuery方法,如果是QM查询直接调用SendQuery

 

private void Form1_Load(object sender, EventArgs e)
{
  //目标主机的响应很快,因此在发送组播之前要先监听本机的5353端口,一旦有目标主机往本机的5353端口发送数据可以马上处理

  //先新建Udp监听本机5353端口
     UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);

   //SocketOptionLevel:指定要设置哪个级别的选项。在这里使用的是 SocketOptionLevel.Socket,表示要设置套接字级别的选项。

   //SocketOptionName.ReuseAddress:允许同一个套接字地址在同一端口上立即重新使用,无需等待之前的连接关闭(理解为共享同一个5353端口,这样运行时才不会报错5353端口被占用)
   udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true);//设置 UDP 客户端的套接字选项

   udpClient.Client.Bind(new IPEndPoint(IPAddress.Parse("本机以太网IP"), 5353)); // 设置监听本机5353端口

   udpClient.BeginReceive(ReceiveCallback, udpClient); // 开始监听并接收Udp单播数据




  //不用设置IP地址和5353端口,默认IP就是224.0.0.251,默认端口是:5353
   MulticastService mdns = new MulticastService();
    mdns.NetworkInterfaceDiscovered += (s, t)
        => mdns.SendUnicastQuery(new DomainName("DomainName查询.local"), DnsClass.IN, type: DnsType.ANY);
    mdns.AnswerReceived += OnGoodDnsMessage;
    mdns.QueryReceived += OnGoodDnsMessage;
    mdns.MalformedMessage += OnBadDnsMessage;
    mdns.Start();
}

//接收并处理Udp单播数据包
private void ReceiveCallback(IAsyncResult ar)
{
  UdpClient client = (UdpClient)ar.AsyncState;
  try
  {
    
    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); // 定义远程端点变量

    byte[] receivedData = client.EndReceive(ar, ref remoteEP);
    txtLogs.AppendText($"--------------------------------------------------------------------\r\n");
    txtLogs.AppendText($"IP:{remoteEP.Address},长度:{receivedData.Length}\r\n");

    //Message可以把字符数组转成Dns报头,方便处理
    Makaretu.Dns.Message message = new Makaretu.Dns.Message();
    message.Read(receivedData, 0, receivedData.Length);
    if (message.AdditionalRecords.Count() > 0)
    {
      var test = message.AdditionalRecords;
      ResourceRecord rrObj = message.AdditionalRecords.FirstOrDefault(t => t.Type == DnsType.TXT);

      if (rrObj != null)
      {
        var txtRecord = (TXTRecord)rrObj;
        txtLogs.AppendText($"----------------解析---------------\r\n");
        foreach (string rrStr in txtRecord.Strings)
        {
          txtLogs.AppendText($"{rrStr}\r\n");
        }
      }
    }
  }
  catch(Exception ex)
  {
    txtLogs.AppendText(ex.ToString());
  }
  // 继续监听数据包  
  client.BeginReceive(new AsyncCallback(ReceiveCallback), client);
}

private void OnBadDnsMessage(object sender, byte[] bytes)
{
}

//接收多播数据并处理,目标主机发送多播情况下触发,因为本次主机是单播因此不会触发这个方法
private void OnGoodDnsMessage(object sender, MessageEventArgs e)
{
    try
    {
        //查看应答信息
        if(e.Message.AdditionalRecords.Count > 0)
        {
            foreach (ResourceRecord rr in e.Message.AdditionalRecords)
            {
                txtLogs.AppendText($"DomainName:{rr.Name},Canonical:{rr.CanonicalName},Type:{rr.Type.ToString()}\r\n");
                string resultStr = rr.ToString();
                byte[] byteArray = rr.GetData();
                txtLogs.AppendText($":{resultStr},[DataLength]{byteArray.Length}\r\n");
            }
        }

        if (e.Message.Answers.Count > 0)
        {
            txtLog2.AppendText($"\r\n***************Answers*****************\r\n");
            foreach (ResourceRecord rr in e.Message.Answers)
            {
                txtLog2.AppendText($":{rr.ToString()}\r\n");
            }
        }
    }
    catch(Exception ex)
    {
        txtLogs.AppendText(ex.ToString());
    }
}

  

 

 

 

----------------解析结果如下---------------
name=1.uos.test.tc
ver=设备软件版本号
ip=10.0.0.64
mac=32:44:83:d2:c3:b0
属性名=yes
app-online=yes//设备是否在线

 

posted on 2023-12-11 17:47  醉驾的猫  阅读(89)  评论(0编辑  收藏  举报

导航