【问题标题】:Why do I get different output from within a java applet then from native java?为什么我从 Java 小程序中获得不同的输出,然后从本机 Java 获得不同的输出?
【发布时间】:2016-04-23 18:23:52
【问题描述】:

我有以下类定义,它扩展了 Applet:

public class TestApplet extends Applet {  
  public static void main(String []argv) {
    TestApplet a = new TestApplet();
    InetAddress b = a.justATest();
    if (b != null) {
      System.out.println(b.getHostAddress());
    }
    if (a.hasError()) {
      System.out.println(a.getErrorTrace());
    }
  }

  public InetAddress justATest(String ip) {
    err = null;
    try {
      final DatagramChannel ch = DatagramChannel.open();
      final InetSocketAddress s = new InetSocketAddress(InetAddress.getByName(ip), 53);
      final InetSocketAddress c = new InetSocketAddress((InetAddress)null, 0);

      class testAction implements PrivilegedExceptionAction<Object> {
        public Object run() throws IOException {
          ch.bind(c);
          try {
            ch.connect(s);
          } catch (NoRouteToHostException ex) {
          }
          return null;
        }
      }

      testAction a = new testAction();
      try { 
        AccessController.doPrivileged(a);
      } catch (PrivilegedActionException pae) {
        Exception ex = pae.getException();
        if (ex instanceof IOException) {
          throw (IOException)ex;
        } else { 
          throw (RuntimeException)ex;
        }
      }
      return ((InetSocketAddress)ch.getLocalAddress()).getAddress();
    } catch (Exception ex) {
      err = ex;
      return null;
    }
  }
}

代码只是创建了一个DatagramSocket,绑定并“连接”它,然后获取本地地址。当我在命令行上运行以下命令时,我得到以下输出:

$ java TestApplet 2001:db8::1
0:0:0:0:0:0:0:0
$ java TestApplet 192.0.2.1
192.168.1.3

这是预期的行为。 192.168.1.3 是我自己的地址。 ANY IPv6 地址 (0:0:0:0:0:0:0:0) 是预期的,因为我目前没有 IPv6 访问权限。

现在,当我使用以下代码从浏览器运行代码时:

function deployApplet() {
  dtjava.embed({
      id: 'test-applet',
      url: 'testapplet.jnlp',
      width: 1,
      height: 1,
      placeholder: "appletPlaceholder",
    },
    {},
    {
      onJavascriptReady: function(id) {
        var applet = document.getElementById(id);
        var addr;
        addr = applet.justATest("192.0.2.1");
        if (addr != null) {
          console.log(addr.getHostAddress());
        }
        if (applet.hasError()) {
          console.log(applet.getErrorTrace());
        }
        addr = applet.justATest("2620:db8::1");
        if (addr != null) {
          console.log(addr.getHostAddress());
        }
        if (applet.hasError()) {
          console.log(applet.getErrorTrace());
        }
      },
    }
  );
}
dtjava.addOnloadCallback(deployApplet);

运行小程序的 jar 文件已签名,我在 jnlp 文件中有以下内容:

<security>
  <all-permissions />
</security>

如果没有这些规定(以及代码中包含的 doPrivileged() 包装器),我将获得权限失败。

现在,我在浏览器中运行它并在 Web 控制台中获得以下输出:

127.0.0.1
127.0.0.1

从浏览器环境运行时我会得到与命令行不同的输出的任何原因?

请注意,除了getLocalAddress() 的输出之外,该通道的行为似乎与预期相同。我在不太简化的上下文中使用此代码来发送 DNS 查询,并且没有其他问题(我可以看到)。通信,包括connect()read()write() 调用,在小程序中运行良好。

【问题讨论】:

  • 您的频道绑定了通配符地址。在独立和嵌入式浏览器的上下文中,这可能会发生不同的定义。
  • 嗯。可能,但似乎不太可能将 127.0.0.1(一个指定的环回地址)用作通配符地址,并且 IPv4 和 IPv6 示例都以这种方式运行,特别是因为我可以验证 IPv4 连接性。跨度>
  • 您指向stackoverflow.com/questions/1510526/… 的指针很有帮助(谢谢!)。它表明权限可能是问题所在。这让我有点吃惊,因为在其他情况下会抛出AccessControlException,但在我的情况下,当getLocalAddress() 被调用而没有doPrivileged() 块时,java 只是返回了127.0.0.1。我将在下面添加答案。

标签: java sockets applet channel


【解决方案1】:

显然,在 DatagramChannel 上调用 getLocalAddress() 也需要位于特权代码块中。这种行为有些误导,因为在其他情况下没有足够的权限在小程序中运行某些东西,AccessControlException 被抛出,但在这种情况下,当从 @987654325 之外的小程序调用 getLocalAddress() 时返回 127.0.0.1 @块。

因此,要修复原始问题中的代码,只需将对 getLocalAddress() 的调用添加到 doPrivileged 块中即可。 justATest()定义如下:

  public InetAddress justATest(String ip) {
    err = null;
    try {
      final DatagramChannel ch = DatagramChannel.open();
      final InetSocketAddress s = new InetSocketAddress(InetAddress.getByName(ip), 53);
      final InetSocketAddress c = new InetSocketAddress((InetAddress)null, 0);

      class testAction implements PrivilegedExceptionAction<InetSocketAddress> {
        public InetSocketAddress run() throws IOException {
          ch.bind(c);
          try {
            ch.connect(s);
          } catch (NoRouteToHostException ex) {
          }
          return ((InetSocketAddress)ch.getLocalAddress());
        }
      }

      testAction a = new testAction();
      try {
        return AccessController.doPrivileged(a).getAddress();
      } catch (PrivilegedActionException pae) {
        Exception ex = pae.getException();
        if (ex instanceof IOException) {
          throw (IOException)ex;
        } else {
          throw (RuntimeException)ex;
        }
      }
    } catch (Exception ex) {
      err = ex;
      return null;
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 2021-03-23
    相关资源
    最近更新 更多