【发布时间】: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