使用Java动态查找LAN中的其他主机

时间:2010-06-16 01:49:39

标签: java networking chat

前段时间我开发了一个小的局域网聊天应用程序。在Java中,它允许与其他主机聊天,发送图像等。虽然它是为了娱乐而创建的,但现在它被用于我工作的地方。

目前,该应用中没有“聊天服务器”。每个客户注册,更新它的状态等等(我喜欢对称设计的想法,而不依赖于在其他机器上运行的服务器)。

相反,每个主机都是一个客户端/服务器,其中包含 hosts.properties 文件,其中包含其他主机的主机名,并且 - 例如 - 在发送大量消息时向每个主机广播/图像/不管。

一开始只有几个主机,所以这个 hosts.properties 文件不是问题。但随着用户数量的增加,更新该文件的需求有点令人生畏。所以现在我决定摆脱它,每次应用程序。启动,动态地找到其他活动主机。

但是,我找不到正确的实现方法。我尝试启动不同的线程,每个线程都在一个已知的IP地址范围内搜索其他主机。像这样的东西(为了便于阅读而简化):

/** HostsLocator */
public static void searchForHosts(boolean waitToEnd) {
    for (int i=0; i < MAX_IP; i+= MAX_IP / threads) {
        HostsLocator detector = new HostsLocator(i, i+(MAX_IP / threads - 1)); // range: from - to
        new Thread(detector).start();                 
    }
}

public void run() {
    for (int i=from; i<=to; i++)
        findHosts( maskAddress + Integer.toString(i) );
}

public static boolean findHosts(String IP) {
    InetAddress address = InetAddress.getByName(IP);
    if ( address.isReachable(CONNECTION_TIME_OUT) )
        // host found!
}

然而:

  • 使用 CONNECTION_TIME_OUT (500毫秒)中的单个线程和较低值,我发现实际处于活动状态的主机的主机未找到状态错误。
  • CONNECTION_TIME_OUT (5000毫秒)中的值很高,只有一个线程需要永远结束
  • 由于碰撞,有几个线程我也发现了与第一个类似的问题。

所以...我猜有更好的方法来解决这个问题,但我找不到它。有什么建议?谢谢!

6 个答案:

答案 0 :(得分:5)

您可以尝试UDP广播到特定端口。网络上所有正在运行的应用程序实例都可以侦听该端口,然后使用将其标识为主机的消息进行响应。

答案 1 :(得分:2)

您可以使用UDP轻松完成此操作。 Check this tutorial例如。

答案 2 :(得分:2)

使用Bonjour / Zeroconf。

The jmdns project拥有您所需要的一切。

答案 3 :(得分:1)

在java中查找lan中的所有主机执行java命令并将结果添加到JList

这里有一些小代码,可以帮助你在windows中读取局域网中的所有主机,其他操作系统会有其他命令,请看下面的代码

try {

    Runtime rt = Runtime.getRuntime();
    FileWriter write=new FileWriter("mylist.txt");
    BufferedWriter writer=new BufferedWriter(write);
    Process pr = rt.exec("net view");

    BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));

    String line=null;
    String hosts="";
    while((line=input.readLine()) != null) {
        Thread.sleep(100);
        if((!(line.equals("")))&&(!(line.equalsIgnoreCase("Server Name            Remark")))&&(!(line.equalsIgnoreCase("-------------------------------------------------------------------------------")))&&(!(line.equalsIgnoreCase("The command completed successfully.")))) 
        {
            line=line.replace('\\',' ');
            line=line.trim();
            listModel.addElement(line);
            hosts=hosts+line.trim()+",";
            hosts=hosts.trim();
        }
    }
    writer.write(hosts);
    writer.close();
    } catch(Exception e) {
        System.out.println(e.toString());
        e.printStackTrace();
    }

答案 4 :(得分:0)

每个主持人都会跟踪他们遇到的所有主机。关闭时,将已知主机保存到文件,并在下次启动时重复使用。

每隔这么多分钟,向每个已知主机发送所有已知主机的列表。

那样

a)无网络扫描
b)新主机将在网络中传播

然后当一个新主持人加入时,他只需要知道另外一个主人就可以了解每个人。

从更新列表中删除一周内未见或从新IP中看到的主机。

答案 5 :(得分:0)

您可以尝试使用DNS service discovery

似乎有一个项目on sourceforge(我没有看过,除了粗略的搜索......)