我有一些仅支持 IPv6 的主机。我可以成功地对它执行 curl 请求 通过 curl
$ curl -I my.ip.v6.only.host
HTTP/1.1 200 OK
但是当我尝试从 java 获取它时出现错误:
HttpGet httpget = new HttpGet("http://my.ip.v6.only.host");
CloseableHttpResponse response = httpclient.execute(httpget);
堆栈跟踪:
INFO: I/O exception (java.net.NoRouteToHostException) caught when processing request to {}->http://my.ip.v6.only.host: No route to host
Mar 17, 2015 7:42:23 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request to {}->http://my.ip.v6.only.host
java.net.NoRouteToHostException: No route to host
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:72)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:123)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at MainTest.main(MainTest.java:25)
java v1.7.0_65 和 v1.8.0_40,MacOS 10.10.2 上出现问题。在之前的 MacOS 10.9.5 版本上运行良好。
这是怎么回事? curl 可以访问主机,而 java 无法访问主机。
另外,我尝试过 -Djava.net.preferIPv6Addresses=true 和 -Djava.net.preferIPv4Stack=false 但它无济于事。
UPD 在 OpenJDK 中发现了一个相关的错误,JDK-8015415
UPD 2 当我尝试使用有线连接而不是 wifi 时,它帮助了我。很奇怪。
最佳答案
可能是AirDrop + Java配合的问题。
简答 - 尝试:
$ sudo ifconfig awdl0 down
调查以下问题(感谢 Sergey Shinderuk):
我们在java中有这样的代码可以重现:
import java.net.Socket;
public class Test {
public static void main(String[] args) throws Exception {
new Socket("2a02:6b8::3", 80); // ya.ru
}
}
当我们使用 WiFi 时,出现异常:java.net.NoRouteToHostException: No route to host
虽然使用 telnet 一切正常:
$ telnet 2a02:6b8::3 80
Trying 2a02:6b8::3...
Connected to www.yandex.ru.
Escape character is '^]'.
^C
当我们关闭 wifi 并使用有线连接时 - 一切正常。但如果我们使用有线连接,但 wifi 已打开 - 此 java 代码将无法运行。这很奇怪。
我们需要比较 java 和 telnet 之间 connect(2) 的参数。
$ sudo dtrace -qn 'syscall::connect:entry { print(*(struct sockaddr_in6 *)copyin(arg1, arg2)) }' -c './telnet 2a02:6b8::3 80'
struct sockaddr_in6 {
__uint8_t sin6_len = 0x1c
sa_family_t sin6_family = 0x1e
in_port_t sin6_port = 0x5000
__uint32_t sin6_flowinfo = 0
struct in6_addr sin6_addr = {
union __u6_addr = {
__uint8_t [16] __u6_addr8 = [ 0x2a, 0x2, 0x6, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3 ]
__uint16_t [8] __u6_addr16 = [ 0x22a, 0xb806, 0, 0, 0, 0, 0, 0x300 ]
__uint32_t [4] __u6_addr32 = [ 0xb806022a, 0, 0, 0x3000000 ]
}
}
__uint32_t sin6_scope_id = 0
}
您可以看到我们将 connect(2) 的第二个参数打印为 struct sockaddr_in6。您还可以看到所有预期信息:AF_INET6、端口 80 和 ipv6-address。
Make a note: we've launched
./telnet, nottelnet-dtracecan't work with system binaries signed by Apple. So we should copy it.
Java 也一样:
$ sudo dtrace -qn 'syscall::connect:entry { print(*(struct sockaddr_in6 *)copyin(arg1, arg2)) }' -c '/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/java Test'
[...]
struct sockaddr_in6 {
__uint8_t sin6_len = 0
sa_family_t sin6_family = 0x1e
in_port_t sin6_port = 0x5000
__uint32_t sin6_flowinfo = 0
struct in6_addr sin6_addr = {
union __u6_addr = {
__uint8_t [16] __u6_addr8 = [ 0x2a, 0x2, 0x6, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3 ]
__uint16_t [8] __u6_addr16 = [ 0x22a, 0xb806, 0, 0, 0, 0, 0, 0x300 ]
__uint32_t [4] __u6_addr32 = [ 0xb806022a, 0, 0, 0x3000000 ]
}
}
__uint32_t sin6_scope_id = 0x8
}
正如我们所见,主要区别在于 telnet 发送 sin6_len == 0 而 java - sin6_scope_id = 0x8。主要问题恰恰在 sin6_scope_id 中。 telnet 和 curl 发送 scope_id == 0,但是 java - 0x8。而当我们使用有线连接时,java发送scope_id == 0xb。
为了清楚起见,我们尝试使用 telnet 重现 scope_id 的问题。
使用 WiFi 可以:
$ telnet 2a02:6b8::3%0 80
Trying 2a02:6b8::3...
Connected to www.yandex.ru.
$ telnet 2a02:6b8::3%8 80
Trying 2a02:6b8::3...
telnet: connect to address 2a02:6b8::3: No route to host
telnet: Unable to connect to remote host
$ telnet 2a02:6b8::3%b 80
Trying 2a02:6b8::3...
Connected to www.yandex.ru.
因此 telnet 可以连接 0xb,但不能连接 0x8。
看来这段 java 代码的正确位置是: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/8fe85977d5a6/src/solaris/native/java/net/net_util_md.c#l105
我们已经看到 scope_id 填充了私有(private)字段 java.net.NetworkInterface.defaultIndex 的值,其中包含一些默认接口(interface)的索引。
我们可以用代码打印所有索引:
import java.lang.reflect.Field;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List<NetworkInterface> netins = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface netin : netins) {
System.out.println(netin + " " + netin.getIndex());
}
Field f = NetworkInterface.class.getDeclaredField("defaultIndex");
f.setAccessible(true);
System.out.println("defaultIndex = " + f.get(NetworkInterface.class));
}
}
在无线网络上:
$ java Netif
name:awdl0 (awdl0) 8
name:en0 (en0) 4
name:lo0 (lo0) 1
defaultIndex = 8
有线
$ java Netif
name:en4 (en4) 11
name:lo0 (lo0) 1
defaultIndex = 11
有线+wifi
$ java Netif
name:awdl0 (awdl0) 8
name:en4 (en4) 11
name:en0 (en0) 4
name:lo0 (lo0) 1
defaultIndex = 8
wifi连接时,defaultIndex == 8,默认接口(interface)为awdl0。
所以我们只是
$ sudo ifconfig awdl0 down
Java 代码有效。
还有:
关于java - 无法从 Java 连接到仅支持 IPv6 的主机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29103828/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r