版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1454500
android平台默认不支持SMB协议,所以无法直接通过主机名访问局域网的设备。如果通过主机名需要访问局域内的设备,就需要将局域网内的主机名解析为IP地址,通过IP地址访问。
所以现在问题就变成了,如何将局域网内的主机名转换为对应的IP地址?
第三方的开源库jcifs可以解决这个问题。根据jcifs官网的说明,这是一个纯java的开源库,实现CIFS/SMB 网络协议,我只是想把主机名解析为IP地址而已,而它实现的功能远超过我需要的。好了,就是它了。
官方网站提供的版本已经几年没更新了,而且只支持SMB1协议,对于新的操作系统(比如如Win10要求SMB2/3)就不能支持,所以官方网站建议使用其他的SMB开源库:
因为jcifs-ng
与原始的jcifs
库的调用方法类似,所以我选择使用前者jcifs-ng,支持SMB2
首先在pom.xml中添加依赖库
<dependency>
<groupId>eu.agno3.jcifs</groupId>
<artifactId>jcifs-ng</artifactId>
<version>2.1.2</version>
<!-- 因为只用到jcifs-ng的netbios主机名解析功能, 所以用不到bcprov-jdk15on提供的加密功能,在这里排除之 -->
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
如下是基于jcifs-ng解析局域网主机名的测试代码,使用非常简单,在android,win7,win10下测试通过
import org.junit.Test;
import jcifs.Address;
import jcifs.NameServiceClient;
import jcifs.context.SingletonContext;
import jcifs.netbios.NameServiceClientImpl;
// 用于android平台测试的注释
//@RunWith(AndroidJUnit4.class)
public class Jcifs2Test {
@Test
public void test3() {
try {
// 创建NameServiceClient实例,这个对象可以作为全局变量使用
NameServiceClient nsc = new NameServiceClientImpl(SingletonContext.getInstance());
{
// 提供的主机名返回所有绑定的地址对象
// 返回的IP地址并不一定都能被本机访问到
Address[] addrs = nsc.getAllByName("landtalkhost", true);
for(Address address : addrs){
System.out.printf("%s\n",address.toInetAddress());
}
}
{
System.out.println("============");
// 根据提供的主机名解析为Address对象,使用这个方法返回的是本机可访问的IP地址
Address address = nsc.getByName("landtalkhost");
System.out.printf("%s %s\n",address,address.getHostAddress());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行输出:
landtalkhost/192.168.10.231
landtalkhost/192.168.100.202
landtalkhost/fe80:0:0:0:fddf:21ed:916a:be60%11
============
landtalkhost/192.168.10.231
参考资料