现在有一个比较恶心的需求,需要客户端扫描开启了 49494 端口( PhotoShop Server )的 Host ,网络掩码是 255.255.248.0 ,一个子网 2000 多个主机,现在的策略是每 128 个 IP 分配一个线程进行扫描,先判断网络是不是可达,如果可达的话尝试和 49494 端口建立 Socket 连接,连接成功则视为该 Host 开启了 PhotoShop Server 。现在扫描一遍大概耗时 8 秒,感觉还是太慢,并且线程数过多( 16 个),有什么更好的办法么 ToT
1
shepherd 2015-12-31 13:14:50 +08:00 via Android
客户端是要把整个网络里开了端口的机器都扫出来吗?还是只有要扫到可用的 host 就行。如果是发现全部, 2000 多个机器,光 ping 都要好久,在没有辅助方法的情况下,单靠客户端去扫,是肯定要花一些时间的。如果客户端的使用环境比较固定,可以考虑在网络环境中驾一个机器负责扫,客户端只要向该机器获取列表即可。如果不是要发现全部 host ,就优化一下客户端扫描的算法,比如不要按 ip 的顺序扫,考虑做个散列算法什么的随机去扫等等。再不然,研究一下 Photoshop server 的协议,看看有没有什么广播之类的功能,在客户端上处理一下。
|
2
sodaless OP @shepherd 要发现全部,并且因为是园区网络, IP 地址经常变化。目前的问题是整个子网里可达的 IP 地址不多,扫描线程遇到不可达的 IP 时会等待直到达到超时时间后(目前设置了 150ms )才会继续扫描下一个 IP ,和这个端口建立的还必须是 TCP 连接,我也想看看能 PS Server 会不会发广播之类的,目前还没从文档上看到,官方的 sample 和文档也是一团糟
|
3
wu360463231 2015-12-31 13:38:31 +08:00
能在客户端运行多一个进程吗,可以的话直接写个 UDP 广播接收反馈的。这样每个子网 UDP 广播下就知道哪些主机可用
|
4
sodaless OP @wu360463231 可以多一个进程,在这里 UDP 广播该怎么用?求指教。
|
5
TheCure 2015-12-31 13:49:09 +08:00
为什么要去检查 IP 是否可达啊,直接发个 SYN 包不就行了,反正你们也是独立 IP,一口气发 2000 个 SYN 包,然后看谁回复了 ACK 呗.
但是这个方法需要用 raw socket 也就是你要有 root 权限,这在安卓上应该不好办. 我的方法和 1L 一样,找台机器做 relay,机器上装个 zmap,nmap 之类的速度嗖嗖的,然后你去拿列表. 至于 UDP 广播...园区的路由器是否支持广播都不知道,就算你能广播,也只能扫到一个路由器下的,什么?你要用组播?还是算了吧组播不支持 TCP 的,你还得保证 TCP UDP 端口都同时打开 |
6
zbz 2015-12-31 14:16:39 +08:00
创建 N 个 socket ,以非阻塞的方式分别连接到需要验证的<IP, Port>,然后等待 M 秒后检查连接是否成功。
假设 N 是 1000 , M 是 1 ,那么一秒钟验证 1000 个 IP 毫无压力。 |
8
sodaless OP @zbz 试了下果然效果拔群,有个小问题就是操作太快的话会报“ Host is down ”和“ No route to host ”,不知道是不是被网关给搞了
|
9
zealot0630 2015-12-31 18:33:32 +08:00
No route to host 是未收到 ARP 回应,很可能是 IP 根本没机器使用
Host is down 是对面回应了 ARP ,但是没有回应 SYN ,多半是因为开了防火墙 |
10
tobyxdd 2015-12-31 18:38:37 +08:00
用 nmap 不行么
|
11
ericyl 2015-12-31 20:06:21 +08:00
我之前的做法是开启 socket 长连接,然后 UDP 循环发送消息,其他机器在接收到 UDP 消息后主动连接 socket
|
12
mengskysama 2015-12-31 20:29:35 +08:00
一般学校路由或者三层交换都会限制每秒新建连接数,我们这边限制比较死每个终端 200 。。
|
13
gamexg 2015-12-31 20:31:48 +08:00 via Android
很麻烦吗?
曾经在 vps 上 golang ,开 500 协程扫 google tls ,没发现问题啊。 |
14
LGA1150 2015-12-31 22:22:39 +08:00
Fing Network Tools - Discover any IP network
|
15
sodaless OP Hi all ,问题已经解决,和大家同步一下 solution , NIO 非阻塞式 socket 是一个挺好的办法,但在移动设备上依然不适用,我测试的安卓机器最多同时打开 1024 个连接后就会达到文件打开数的上限,即使队列式处理,主动关闭 socket 后句柄好像也不能即时释放。并且 socket channel 在 finishConnect 的时候会被阻塞,不知道是不是被路由设备限制了。最后的解决办法是使用 mDNS ,广播方式寻找,在 java 上有 JmDNS 库可以使用,在 Android API 16 以上系统有提供 NsdManager 服务,很好使,完美解决。
|