海康 设备 发现(SADPTool原理)

SADPTool原理:

向239.255.255.250:37020发送基于ONVIF协议的 udp 组播,设备会监听 239.255.255.250:37020,收到指令,会向 发送组播的机器,返回设备信息,也会向239.255.255.250:37020 发送 设备信息的 组播。

 

发送 报文(Uuid是Guid,每次都生成一个新的,用同一个,我没有试过,可不可以)

<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>12D17626-0DE1-48DB-97E3-40B106467932</Uuid><Types>inquiry</Types></Probe>

返回报文
<?xml version="1.0" encoding="UTF-8" ?>
<ProbeMatch>
<Uuid>12D17626-0DE1-48DB-97E3-40B106467932</Uuid>
<Types>inquiry</Types>
<DeviceType>139991</DeviceType>
<DeviceDescription>CS-C6TC-32WFR</DeviceDescription>
<DeviceSN>CS-C6TC-32WFR0120170327CCCH738231995</DeviceSN>
<CommandPort>8000</CommandPort>
<HttpPort>80</HttpPort>
<MAC>54-c4-15-9a-38-72</MAC>
<IPv4Address>172.20.20.100</IPv4Address>
<IPv4SubnetMask>255.255.255.0</IPv4SubnetMask>
<IPv4Gateway>172.20.20.254</IPv4Gateway>
<DHCP>false</DHCP>
<AnalogChannelNum>0</AnalogChannelNum>
<DigitalChannelNum>1</DigitalChannelNum>
<SoftwareVersion>V5.2.3build 180804</SoftwareVersion>
<DSPVersion>V1.0 build 180731</DSPVersion>
<BootTime>2018-10-18 21:30:10</BootTime>
<OEMInfo>N/A</OEMInfo>
<Activated>true</Activated>
<PasswordResetAbility>false</PasswordResetAbility>
</ProbeMatch>

通过 wireshark 抓包发现,发送 ONVIF协议后,还会 广播 一个 包

但是不知道,是做何作用,我用SharpPcap 模拟发送了一个EarthNet II 的包,这个包 是固定不变的。

EarthNet II 的包,C# 原生 Socket 貌似不支持,raw_Socket 写起来太繁琐了,SharpPcap 另一个用处是可以基于网卡抓包。

搜索设备代码:


        public void SearchDecives()
        {
            //EtherNetII 协议
            byte[] SearchIpCameraByte = new byte[]{
                0xff ,0xff ,0xff ,0xff ,0xff ,0xff ,//目的地Mac
                0x00 ,0x15 ,0x5d ,0xe6 ,0xaa ,0x0b ,//源地址Mac
                0x80 ,0x33 ,//协议类型(0x8033萤石自定义类型)
                0x21 ,0x02,//发送数据   
                0x01 ,0x42 ,0x00 ,0x00 ,0x24 ,0x03 ,0x06 ,0x04 ,0x03 ,0x00 ,0x13 ,0x82 ,0x00 ,0x15 ,0x5d ,0xe6,  
                0xaa ,0x0b ,0xa9 ,0xfe ,0x50 ,0x50 ,0xff ,0xff ,0xff ,0xff ,0xff ,0xff ,0x00 ,0x00 ,0x00 ,0x00,  
                0x00 ,0x00 ,0x00 ,0x00 ,0xfe ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x64 ,0x7e ,0x5d ,0xb0,  
                0x9e ,0x93 ,0xcd ,0x07 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,  
            };
            var devices = CaptureDeviceList.Instance;
            Console.Write("---------------------------");
            // differentiate based upon types
            foreach (ICaptureDevice dev in devices)
            {
                if (dev is AirPcapDevice)
                {
                    // process as an AirPcapDevice
                }
                else if (dev is WinPcapDevice)
                {
                    dev.Open();
                    //dev.Capture();
                    //dev.StartCapture();
                    dev.SendPacket(SearchIpCameraByte);
                    Thread.Sleep(1000);
                    //dev.StopCapture();
                    //dev.Close();
                    // process as an WinPcapDevice
                }
                else if (dev is LibPcapLiveDevice)
                {
                    // process as an LibPcapLiveDevice
                }
            }
            return;
        }

        /// <summary>
        /// 查找设备
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            SendInQuiry();
            SearchDecives();
            SendMSearch();
        }

        /// <summary>
        /// 搜索upnp 设备
        /// 向ssdp服务地址239.255.255.250:1900组播发送数据
        /// </summary>
        public void SendMSearch()
        {
            //向ssdp服务地址239.255.255.250:1900组播发送数据
            IPEndPoint ipend = new IPEndPoint(IPAddress.Any, 0);
            UdpClient client = new UdpClient(ipend);
            client.EnableBroadcast = false;
            client.JoinMulticastGroup(IPAddress.Parse("239.255.255.250"));
            IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);
            byte[] buf = Encoding.Default.GetBytes("M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:upnp:rootdevice\r\nMX:3\r\n\r\n");
            client.Send(buf, buf.Length, multicast);
                          
            //异步接收数据
            //client.BeginReceive(new AsyncCallback(ReceiveBack), client);

            //设置网络超时时间,一段时间未接收到数据时自动退出
            //client.Client.ReceiveTimeout = 150;

            //单播接收数据
            //while (true)
            //{
            //    byte[] value = client.Receive(ref ipend);
            //    string msg = Encoding.Default.GetString(value);
            //    //OLog.Info(msg);
            //    Console.WriteLine(msg + "-" + ipend.Address.ToString());
            //}
        }

        /// <summary>
        /// 发送设备探究
        /// 向ssdp服务地址239.255.255.250:37020组播发送数据
        /// </summary>
        public void SendInQuiry()
        {
            var uuid = Guid.NewGuid().ToString().ToUpper();
            //<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>A207AD1A-962B-480B-A32C-4B0D98CBA0D4</Uuid><Types>inquiry</Types></Probe>
            var InQuiry = new byte[]{
                    0x3c ,0x3f ,0x78 ,0x6d ,0x6c ,0x20,   
                    0x76 ,0x65 ,0x72 ,0x73 ,0x69 ,0x6f ,0x6e ,0x3d ,0x22 ,0x31 ,0x2e ,0x30 ,0x22 ,0x20 ,0x65 ,0x6e,   
                    0x63 ,0x6f ,0x64 ,0x69 ,0x6e ,0x67 ,0x3d ,0x22 ,0x75 ,0x74 ,0x66 ,0x2d ,0x38 ,0x22 ,0x3f ,0x3e,   
                    0x3c ,0x50 ,0x72 ,0x6f ,0x62 ,0x65 ,0x3e ,0x3c ,0x55 ,0x75 ,0x69 ,0x64 ,0x3e
                }.
                Concat(System.Text.Encoding.UTF8.GetBytes(uuid)).//uuid
                Concat(new byte[]{
                    0x3c ,0x2f ,0x55 ,0x75 ,0x69 ,0x64 ,0x3e ,0x3c ,0x54 ,0x79 ,0x70 ,0x65 ,0x73 ,0x3e ,0x69,   
                    0x6e ,0x71 ,0x75 ,0x69 ,0x72 ,0x79 ,0x3c ,0x2f ,0x54 ,0x79 ,0x70 ,0x65 ,0x73 ,0x3e ,0x3c ,0x2f,   
                    0x50 ,0x72 ,0x6f ,0x62 ,0x65 ,0x3e
                }).ToArray();
            IPEndPoint ipend = new IPEndPoint(IPAddress.Any, 0);
            UdpClient client = new UdpClient(ipend);
            client.EnableBroadcast = false;
            client.JoinMulticastGroup(IPAddress.Parse("239.255.255.250"));
            IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 37020);
            client.Send(InQuiry, InQuiry.Length, multicast);
        }

监听组播代码:

private void button2_Click(object sender, EventArgs e)
        {
            //接收组播数据
            Thread t = new Thread(new ThreadStart(RecvThread));
            t.IsBackground = true;
            t.Start();
            //Socket recv_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            //recv_socket.Bind(new IPEndPoint(IPAddress.Any, 1900));
            //recv_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveMessage, recv_socket);
        }

        /// <summary>
        /// 获取 ssdp 组播
        /// ssdp地址固定:239.255.255.250:1900
        /// 海康设备组播到 37020 端口
        /// </summary>
        void RecvThread()
        {
            //绑定组播端口   
            UdpClient client = new UdpClient(37020);
            client.EnableBroadcast = false;
            client.JoinMulticastGroup(IPAddress.Parse("239.255.255.250"));
            IPEndPoint mult = null;
            while (true)
            {
                byte[] buf = client.Receive(ref mult);
                string msg = Encoding.Default.GetString(buf);
                Console.WriteLine(msg);
                MessageBox.Show(msg);
                //Console.WriteLine(mult.Address.ToString());
            }
        }

还可以用 ARP 映射原理 获取 局域网 所有机器的MAC地址,根据MAC 前6位判断是 哪家生产的设备,同一企业生产的 网络设备mac地址 前6位一般是固定的。

海康设备Mac地址 都是54-c4-15 开头的

我这里用的是 cmd arp -a,取arp映射的,也可以 sharppcap抓包,或者Windows api 发送arp 协议 包,取返回值

private static string GetARPResult()
        {
            Process p = null;
            string output = string.Empty;
            try
            {
                p = Process.Start(new ProcessStartInfo("arp", "-a")
                {
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardOutput = true
                });
                output = p.StandardOutput.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw new Exception("IPInfo: Error Retrieving 'arp -a' Results", ex);
            }
            finally
            {
                if (p != null)
                {
                    p.Close();
                }
            }
            return output;
        }

 

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值