.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//设备是否在线
浙公网安备 33010602011771号