如何发现网络中的设备 设备发现协议(收集)

如何发现网络中的设备(收集)

如何发现网络中的设备(收集)

好吧,每次要SSH到树莓派都很麻烦,我是没找什么办法,每次都得连上显示器鼠标键盘。才能知道IP地址。

看了点python,写了个脚本来发出 ip 地址。这样就省事多了。

缺陷:发现启动时有可能早于树莓派网络初始化,会导致UDP服务初始化出现问题。脚本里面延时 30秒执行。

在树莓派4 测试通过。

=================配置树莓派

SSH登录树莓派

sudo nano /etc/rc/local

输入python脚本

重启树莓派

这个时候怎么看我们的程序是否自启动了呢。登录树莓派 执行 sudo systemctl status rc-local 看看 FindIPUDPServer 是否已经起来了。

=================Python 脚本

链接:https://pan.baidu.com/s/1DJ0JY71MutlB7IFl_HD2Fw 密码:qexh

=================Android客户端:

APP 截图

源码FindIPUDPServer.py

11

# from time import ctime
import socket
# from socket import *
import uuid
import time
import os

import time
import logging

from logging import handlers

# 获取MAC地址
def get_mac_address():
    mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
    return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])


# 获取IP地址
def get_host_ip():
    try:
        my = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        my.connect(('8.8.8.8', 80))
        # ip = my.getsockname()[0]
        ipList = my.getsockname()
    finally:
        my.close()
    return ipList


def _logging(**kwargs):
    level = kwargs.pop('level', None)
    filename = kwargs.pop('filename', None)
    datefmt = kwargs.pop('datefmt', None)
    format = kwargs.pop('format', None)
    if level is None:
        level = logging.DEBUG
    if filename is None:
        filename = 'default.log'
    if datefmt is None:
        datefmt = '%Y-%m-%d %H:%M:%S'
    if format is None:
        format = '%(asctime)s [%(module)s] %(levelname)s [%(lineno)d] %(message)s'

    log = logging.getLogger(filename)
    format_str = logging.Formatter(format, datefmt)
    # backupCount 保存日志的数量,过期自动删除
    # when 按什么日期格式切分(这里方便测试使用的秒)
    th = handlers.TimedRotatingFileHandler(filename=filename, when='H', backupCount=3, encoding='utf-8')
    th.setFormatter(format_str)
    th.setLevel(logging.DEBUG)

    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    #  ch.setFormatter(format)
    log.addHandler(ch)

    log.addHandler(th)
    log.setLevel(level)
    return log


os.makedirs("logs", exist_ok=True)
mylog = _logging(filename='logs/udpserver.log')


print("等待30秒")
mylog.debug("等待30秒")
time.sleep(30)
print("等待结束")
mylog.debug("等待结束")

HOST = ''
PORT = 9999
BUFSIZ = 1024
ADDRESS = (HOST, PORT)

udpServerSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpServerSocket.bind(ADDRESS)  # 绑定客户端口和地址

myname = socket.gethostname()
print("myname:" + myname)
mylog.debug("myname:" + myname)
# myIP = get_host_ip()
# print("myIP:"+myIP)
myIPList = get_host_ip()
# ipListSize = len(myIPList)
# for ip in myIPList:
#     print("myIP:"+str(ip))
print("myIPList:" + str(myIPList))
mylog.debug("myIPList:" + str(myIPList))
macAddress = get_mac_address()
print("macAddress:" + macAddress)
mylog.debug("macAddress:" + macAddress)

while True:
    print("waiting for message...")
    mylog.debug("waiting for message...")
    data, addr = udpServerSocket.recvfrom(BUFSIZ)
    currCode = data.decode('utf-8')
    print("接收到数据:" +currCode)
    mylog.debug("接收到数据:"+currCode)

    # content = '[%s] %s' % (bytes(ctime(), 'utf-8'), data.decode('utf-8'))
    # 发送服务器时间
    if currCode == "TIME":
        content = "Time:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        udpServerSocket.sendto(content.encode('utf-8'), addr)
    # 发送IP地址
    elif currCode == "IP":
        content = "IP:" + str(myIPList)
        udpServerSocket.sendto(content.encode('utf-8'), addr)
    # 发送mac地址
    elif currCode == "MAC":
        content = "MAC:" + macAddress
        udpServerSocket.sendto(content.encode('utf-8'), addr)
    # 发送ip mac地址
    elif currCode == "IP_MAC":
        content = "IP:" + str(myIPList) + "|MAC:" + macAddress
        udpServerSocket.sendto(content.encode('utf-8'), addr)
    # 退出UDP服务端
    elif currCode == "EXIT":
        content = "服务端退出"
        udpServerSocket.sendto(content.encode('utf-8'), addr)
        # print(content)
        break
    # 重启
    elif currCode == "REBOOT":
        content = "服务端重启"
        udpServerSocket.sendto(content.encode('utf-8'), addr)
        print("服务端开始重启")
        mylog.debug("服务端开始重启")
        os.system('shutdown -r now')
        break
    # 关机
    elif currCode == "SHUTDOWN":
        content = "服务端关机"
        udpServerSocket.sendto(content.encode('utf-8'), addr)
        print("服务端开始关机")
        mylog.debug("服务端开始关机")
        os.system('sudo shutdown -h now')
        break
    else:
        udpServerSocket.sendto("Bad Key".encode('utf-8'), addr)

    # content = '[%s] %s %s' % (bytes(ctime(), 'utf-8'), str(myIPList), macAddress)
    # udpServerSocket.sendto(content.encode('utf-8'), addr)
    print('...received from and returned to:', addr)
    mylog.debug('...received from and returned to:', addr)
udpServerSocket.close()
print("服务端退出")
mylog.debug('服务端退出')

22

设备发现协议

网络环境下设备发现是一种比较常见的应用,比如查找打印机与WiFi。那么我们应该如何通过编程实现对网络中的特定设备进行查找呢?

常用的方式有:IP广播与多播,以及基于这两种方式所实现的第三方协议,较著名的有Onvif协议。
我的第二个猜测是使用有限的IP地址范围主动扫描网络并等待正确的响应.不幸的是,这意味着网络使用DHCP来寻址IP地址.

1

除了AirKiss、SmartConfig此类网络应用技巧,我们需要尽可能利用手头开源硬件来测试传统的TCP/UDP连接。其中UDP的组播在物联网应用中有一定的重要意义。主要的UDP组播应用协议有:

mDNS
SSDP/uPnP
Apple AirPlay
DLNA,各类媒体播放器
IP组播与IGMP
IGMP(Internet Group Management Protocol)协议告诉路由器,在所在子网内有客户端对发送到某一个组播组的数据感兴趣,这样当该组的数据到达后,路由器会转送给所有感兴趣的客户端。

Windows 失败原因
之间发现,凡是Windows主机参与的IP组播都是失败的。首先怀疑WiFi路由器禁止了IGMP和uPnP服务,测试下来,同一WiFi局域网内,电视和手机的媒体推送没有任何问题。

但即便开启了Windows的Bonjour服务,关闭了防火墙,依然失败。推测Windows的网路配置上依然存在问题,这是Windows 10以及Ubuntu子系统无法侦听和推送多播报文的主要原因。Windows 10自带的Ubuntu子系统受控于操作系统防火墙,无法收发组播报文。抛出一个错误:

allankliu@allankliu-HP:/mnt/c/Users/allankliu$ iperf -s -u -B 224.0.67.67 -i 1
bind failed: Cannot assign requested address
而运行于Windows中的虚拟机,因为其网络配置是桥接模式,Ubuntu虚拟机可以直接从路由器获得IP地址,Windows防火墙对其没有作用。是可以收发组播报文的。

今早拿Ubuntu 12.04(Windows中VirtualBox中虚拟机)和树莓派Raspbian做了测试,Linux之间组播没有任何问题。测试工具使用了iperf,下一步将采用Python socket做测试。

iperf for Linux
pi@raspberrypi ~ $ iperf -c 224.0.67.67 -u --ttl 5 -t 10

Client connecting to 224.0.67.67, UDP port 5001
Sending 1470 byte datagrams
Setting multicast TTL to 5
UDP buffer size: 160 KByte (default)

[ 3] local 192.168.1.25 port 35294 connected with 224.0.67.67 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 1.25 MBytes 1.05 Mbits/sec
[ 3] Sent 893 datagrams
allankliu@ubuntu-server-vm:~$ iperf -s -u -B 224.0.67.67 -i 1

Server listening on UDP port 5001
Binding to local address 224.0.67.67
Joining multicast group 224.0.67.67
Receiving 1470 byte datagrams
UDP buffer size: 160 KByte (default)

[ 3] local 224.0.67.67 port 5001 connected with 192.168.1.25 port 35294
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0- 1.0 sec 128 KBytes 1.05 Mbits/sec 1.017 ms 0/ 89 (0%)
[ 3] 1.0- 2.0 sec 129 KBytes 1.06 Mbits/sec 0.972 ms 0/ 90 (0%)
[ 3] 2.0- 3.0 sec 128 KBytes 1.05 Mbits/sec 0.723 ms 0/ 89 (0%)
[ 3] 3.0- 4.0 sec 128 KBytes 1.05 Mbits/sec 6.029 ms 0/ 89 (0%)
[ 3] 4.0- 5.0 sec 128 KBytes 1.05 Mbits/sec 1.236 ms 0/ 89 (0%)
[ 3] 5.0- 6.0 sec 128 KBytes 1.05 Mbits/sec 2.518 ms 0/ 89 (0%)
[ 3] 6.0- 7.0 sec 129 KBytes 1.06 Mbits/sec 1.097 ms 0/ 90 (0%)
[ 3] 7.0- 8.0 sec 128 KBytes 1.05 Mbits/sec 1.024 ms 0/ 89 (0%)
[ 3] 8.0- 9.0 sec 128 KBytes 1.05 Mbits/sec 0.697 ms 0/ 89 (0%)
[ 3] 9.0-10.0 sec 128 KBytes 1.05 Mbits/sec 1.586 ms 0/ 89 (0%)
[ 3] 0.0-10.0 sec 1.25 MBytes 1.05 Mbits/sec 1.577 ms 0/ 893 (0%)
以上是树莓派发,Ubuntu收,反之亦然。

ESP8266
以组播为基础的mDNS/SSDP作为IoT最大的好处就是可以通过这两项服务构建起一个本地的IoT设备生态,无论是办公司、家居、工业、农业、军事等。均可以通过IPv4/v6组播实现自动接入、然后利用TCP/UDP的单播进行后续认证和协同。

ESP8266自带mDNS/SSDP例子。之所以对组播感兴趣也就是因为自己要做些产品而做得实验。

iperf的其他版本
iperf是法国人写的,除了最初的Linux,还支持32bit/64bit Windows,以及Android,iOS,Mac等,主流平台都得到了支持。如果Chrome/Android/iOS移动端的JavaScript runtime支持组播,那么甚至可以不需要Java/C/C++/Python的参与了。

21

udp 单播、组播、广播都可以实现,单为什么我使用udp组播,

请参考我的上一篇 局域网发现之UDP组播

本篇讲解的是如何使用代码来实现局域网发现功能;

我的需求背景:

使用场景,手机上安装有app A,同一局域网内的电视 上安装有app B,要求当app B 这个版本支持来自A的某个互动功能(比如投屏、游戏控制)时,A就应该能搜到到B所在的设备提示给用户,然后用户才进行互动,局域网搜索设备则是互动的第一步也是前提;

局域网发现之UDP组播

https://blog.csdn.net/lixin88/article/details/55209630
局域网发现的意义
局域网发现设备是通信的第一步,通信需要先知道对方的ip地址,因为一般使用 DHCP 动态分配 ip 地址的局域网内,各个主机的 IP 地址是由 DHCP 服务器来帮你分配 IP 地址的。所以在很多情况下,你要知道对方的 IP 地址是比较麻烦的。

因此,局域网发现,我们要解决的事情就是:如何找到局域网内其他设备,并获取到设备的ip;

查询资料之后,发现使用udp单播、组播、广播来实现的方式都有,并且亲测确实都可行,那么哪种更合适呢,这也是我写这篇的目的,让大家对这些有个基本概念和对比;

使用哪种协议实现
udp 不用保证数据可靠性,传输速度快;并且一般tcp是不用于多播场景的;那使用udp如何实现呢?

使用udp 单播、组播还是广播
先来了解什么是单播和组播、广播
单播
只有一个源点网络和一个终点网络。源点网络和终点网络的关系是一对一的。数据报途径的每一个路由器都要将这个分组仅从一个接口转发出去。
图例:

多播
在多播系统中,有一个源点一组终点。这是一对多的关系。在这种类型的通信中,源地址是一个单播地址,而目的地址则是一个组地址。
图例:

单播和组播、广播的区别
多播的优点
q 具有同种业务的主机加入同一数据流,共享同一通道,节省了带宽和服务器的优点,具有广播的优点而又没有广播所需要的带宽。
q 服务器的总带宽不受客户端带宽的限制。由于组播协议由接收者的需求来确定是否进行数据流的转发,所以服务器端的带宽是常量,与客户端的数量无关。
q 与单播一样,多播是允许在广域网即Internet上进行传输的,而广播仅仅在同一局域网上才能进行。

广播的缺点
q 多播与单播相比没有纠错机制,当发生错误的时候难以弥补,但是可以在应用层来实现此种功能。
q 多播的网络支持存在缺陷,需要路由器及网络协议栈的支持。
多播的应用主要有网上视频、网上会议等。

组播与广播
广播数据报的接收是被动的。
连接到子网上的所有主机都要接收广播数据报,这会增加网络流量,并且子网上的主机增加额外的负担。
UDP广播只能在内网(同一网段)有效,而组播可以较好实现跨网段群发数据。
UDP广播:消耗更多网络带宽,路由器向子网内的每个终端都投递一份数据包,不论这些终端是否乐于接收该数据包;
UDP组播:有了很大优化,只有终端加入到了一个广播组,UDP组播的数据才能被他接收到;
多播数据报的接收是主动的。主机主动加入指定的多播组,才会接收该组的多播数据报。
不同子网内的A,B进行组播通信,依靠IGMP协议;局域网组播,不考虑跨网段的组播实现,因此组播路由协议IGMP与本文要介绍的内容无关;

局域网的多播
多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:
q 局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。
q 预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
q 管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。

初步结论
局域网发现可以使用:
1.udp单播,获取源主机的ip和子网掩码,得到该局域网的ip地址范围,然后使用udp单播轮询 找到对应的目标主机;

2.udp组播,让源主机和目标主机都加到同一个局部多播地址;源主机给该多播地址发送组播消息即可;

3.udp广播,使用广播地址255.255.255.255 来广播定制好的消息;

综合考虑:udp单播轮询比较耗时,而且如果局域网内设备较多,UDP发送过快的话,会导致本地发送缓冲区丢包;接收过慢的话,也会导致接收缓冲丢包;单播和广播一样,对于不需要关心该消息的主机是一种打扰;
因此,使用udp组播来实现局域网发现比使用udp广播更合适;并且我之后会学习mdns和dns-sd,而这两种都是基于udp组播,所以用组播来实现对于后面的深入研究更有意义;
现在,我们来实现一个最简单的局域网发现的demo;具体实现请看下一篇

设备发现协议

网络环境下设备发现是一种比较常见的应用,比如查找打印机与WiFi。那么我们应该如何通过编程实现对网络中的特定设备进行查找呢?

常用的方式有:IP广播与多播,以及基于这两种方式所实现的第三方协议,较著名的有Onvif协议。

1局域网广播
1.1 定义
  广播是一种一对所有的通信模式。有线电视网就是典型的广播型网络,我们的电视机实际上是接受到所有频道的信号,但只将一个频道的信号还原成画面。

广播不用进行网络路径选择,不能穿越路由器。这是为了防止广播数据影响大面积的主机,引起广播灾难。

1.2 优缺点
1.2.1 优点
网络设备简单,维护简单,布网成本低廉。
由于服务器不用向每个客户机单独发送数据,所以服务器流量负载极低。
1.2.2 缺点
无法针对每个客户的要求和时间及时提供个性化服务。
网络允许服务器提供数据的带宽有限,客户端的最大带宽=服务总带宽。例如有线电视的客户端的线路支持100个频道(如果采用数字压缩技术,理论上可以提供 500个频道),即使服务商有更大的财力配置更多的发送设备、改成光纤主干,也无法超过此极限。
不能在广域网上传播,这是为了防止广播风暴。
1.3 广播地址
  每一个网段都有一个广播地址,其格式为 xxx.xxx.xxx.255 的形式。计算方式如下:

网络地址 = IP地址 & 子网掩码

广播地址 = 网络地址 | (~子网掩码)

avahi
mDNS

/etc/avahi/services/sftp-ssh.service

sspd

网络发现客户端,实现sspd协议。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用jmdns发现局域网设备,在局域网内,你要通过一台主机和其他主机进行通信,你需要知道对方的ip地址,但是有些时候,你并不知道对方的ip地址,因为一般使用DHCP动态分配ip地址的局域网内,各个主机的IP地址是由DHCP服务器来帮你分配IP地址的。所以在很多情况下,你要知道对方的IP地址是比较麻烦的。 鉴于发现这篇文章最近的浏览量比较多,晚上也有不少转载,特别声明一下,文章水平可能不大够,只是我当时的一些理解,所以希望大家以批判的角度来看,然后又什么问题欢迎讨论。真心不希望误导大家^_^ mDNS就是来解决这个问题的。通过一个约定俗成的端口号,5353。(这个端口号应该是由IETF组织约定的。)每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少。当然,具体实现要比这个复杂点。 比如,A主机进入局域网,开启了mDNS服务,并向mDNS服务注册一下信息:我提供FTP服务,我的IP是192.168.1.101,端口是21。当B主机进入局域网,并向B主机的mDNS服务请求,我要找局域网内FTP服务器,B主机的mDNS就会去局域网内向其他的mDNS询问,并且最终告诉你,有一个IP地址为192.168.1.101,端口号是21的主机,也就是A主机提供FTP服务,所以B主机就知道了A主机的IP地址和端口号了。 大概的原理就是这样子,mDNS提供的服务要远远多于这个,当然服务多但并不复杂。 在Apple 的设备上(电脑,笔记本,iphone,ipad等设备)都提供了这个服务。很多Linux设备也提供这个服务。Windows的设备可能没有提供,但是如果安装了iTunes之类的软件的话,也提供了这个服务。 这样就可以利用这个服务开发一些局域网内的自动发现,然后提供一些局域网内交互的应用了。
使用SNMP(Simple Network Management Protocol,简单网络管理协议)可以发现大型复杂环境的网络拓扑。以下是一些步骤: 1. 网络设备配置:首先,确保网络的所有设备都已正确配置SNMP协议。每个设备都需要配置相同的SNMP团体字符串(community string),以便允许SNMP管理系统进行查询和获取设备信息。 2. SNMP管理系统:建立一个SNMP管理系统,该系统将作为发现和管理网络拓扑的心。可以使用专门的SNMP管理软件,如Cacti或Nagios等,或自定义开发的软件。 3. 发现设备:使用SNMP管理系统向网络的所有设备发送SNMP查询请求,以获取设备的信息。查询请求可以根据设备的IP地址或子网进行规划,以便逐步发现整个网络。 4. 解析设备响应:当SNMP管理系统收到设备的响应时,它需要解析响应并提取感兴趣的信息。这些信息可以包括设备的基本信息(如设备类型、厂商、固件版本等)以及与网络拓扑相关的信息(如相邻设备的IP地址、接口信息等)。 5. 构建网络拓扑:根据收集到的设备信息和相邻设备的信息,SNMP管理系统可以构建出完整的网络拓扑图。这可以是一个逐步的过程,通过不断发现新的设备并添加到拓扑图来更新图表。 6. 拓扑分析和管理:一旦有了网络拓扑图,就可以使用SNMP管理系统来进行拓扑分析和管理。这包括检测网络的故障、监控网络性能、配置网络设备等。 SNWP管理系统还可以提供通知和报警功能,以便在网络发生故障或异常情况时向管理员发送警报。 值得注意的是,发现大型复杂环境的网络拓扑可能是一个耗时且复杂的过程。因此,在实施前需要进行充分的规划和准备。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值