• IPv6调用java后端接口报错:java.net.SocketException: Protocol family unavailable


      目前需求是java后端的接口需要支持IPv6。先确认linux机器已经绑定了IPv6:

    CMREAD-SV43 apache-tomcat/bin> ifconfig
    eth0      Link encap:Ethernet  HWaddr 2C:76:8A:AF:9E:82  
              inet addr:192.168.11.11  Bcast:192.168.11.111  Mask:255.255.255.0
              inet6 addr: fe80::2e76:8aff:feaf:9e82/64 Scope:Link
              inet6 addr: 2409:8028:8f1:1202::69/64 Scope:Global
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:3032806443 errors:0 dropped:332 overruns:0 frame:0
              TX packets:320990686207 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:256791451048 (244895.4 Mb)  TX bytes:332584238528831 (317177046.3 Mb)
              Memory:f9ec0000-f9ee0000 
    
    eth2      Link encap:Ethernet  HWaddr 9C:8E:99:2A:EE:94  
              inet addr:11.111.11.11  Bcast:11.111.11.11  Mask:255.255.255.192
              inet6 addr: fe80::9e8e:99ff:fe2a:ee94/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:2905011525 errors:0 dropped:0 overruns:0 frame:0
              TX packets:3243480696 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:857178438283 (817469.0 Mb)  TX bytes:948398682892 (904463.4 Mb)
              Interrupt:36 Memory:fc000000-fc012800 
    
    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:62415690585 errors:0 dropped:0 overruns:0 frame:0
              TX packets:62415690585 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:3519258276730 (3356226.2 Mb)  TX bytes:3519258276730 (3356226.2 Mb)

      我们拿网卡二(eth2)的IPv6去调接口,这里注意需要给IPv6地址加上左右中括号,即以这种格式去调

    http://[fe80::9e8e:99ff:fe2a:ee94]:9088/接口名

      结果java报错了:

    <<<HttpConnectionManager.getConnection:  config = HostConfiguration[host=http://[fe80::9e8e:99ff:fe2a:ee94]:9088], timeout = 500 >>>
    <<<Allocating new connection, hostConfig=HostConfiguration[host=http://[fe80::9e8e:99ff:fe2a:ee94]:9088] >>>
    <<<Open connection to [fe80::9e8e:99ff:fe2a:ee94]:9088 >>>
    <<<Closing the connection. >>>
    <<<I/O exception (java.net.SocketException) caught when processing request: Protocol family unavailable >>>
    <<<Protocol family unavailable >>>
    java.net.SocketException: Protocol family unavailable
            at java.net.PlainSocketImpl.socketConnect(Native Method)
            at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
            at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
            at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
            at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
            at java.net.Socket.connect(Socket.java:589)
            at java.net.Socket.connect(Socket.java:538)
            at java.net.Socket.<init>(Socket.java:434)
            at java.net.Socket.<init>(Socket.java:286)
            at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:80)
            at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:122)
            at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
            at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
            at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
            at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
            at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
            at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
            at com.migu.reading.common.utils.HttpTools.sendHttpRequest(HttpTools.java:185)
            at com.migu.reading.servlet.assistant.InterfaceServlet.service(InterfaceServlet.java:163)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at com.migu.reading.auditweb.filter.AuditFilter.doFilter(AuditFilter.java:169)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at com.migu.reading.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:27)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
            at com.huawei.openas.monitor.valve.RequestCounterValve.invoke(RequestCounterValve.java:128)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
            at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)
    <<<Retrying request >>>
    <<<Open connection to [fe80::9e8e:99ff:fe2a:ee94]:9088 >>>
    <<<Closing the connection. >>>
    <<<I/O exception (java.net.SocketException) caught when processing request: Protocol family unavailable >>>

      按理java是自动支持IPv6的,为啥还报错呢?看来应该是环境主动配置了针对IPv4的开关,一找发现在tomcat的bin目录下果然有一个setvmargs.sh的文件设置了java.net.preferIPv4Stack系统属性:

    JAVA_OPTS="$JAVA_OPTS -server -Xmn2457M -Xms6384M -Xmx6384M  -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true -XX:PermSize=5120M -XX:MaxPermSize=5120M  -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly  -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=5 -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0 -Xloggc:gc.log -XX:+PrintGCDetails -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=29331 -Dcom.sun.management.jmxremote.ssl=false"

      该参数默认是false,在支持IPv6的双栈系统上,使用Java的Socket会默认通过底层native方法创建一个IPv6 Socket,这个IPv6 Socket可以同时支持和IPv4或IPv6主机通信。当TCP客户端java.net.preferIPv4Stack设置为true时,如果想创建一个host为IPv6的Socket,会抛出异常java.net.SocketException: Protocol family unavailable,设置为false时则程序可以正常运行。

      类似的,还有另一个系统属性java.net.preferIPv6Addresses,它默认也是false,但值却跟上面属性相反,它支持的是IPv6,配置true时才支持。我们将java.net.preferIPv4Stack改为false后重启系统,问题解决。

      对了,以上两个系统属性也可以在代码里指定:

    System.setProperty("java.net.preferIPv4Stack", "true");
     
  • 相关阅读:
    LAMP环境搭建
    Httpd
    MySQL常用配置和性能压力测试:MySQL系列之十五
    MySQL的高可用实现:MySQL系列之十四
    MySQL的复制:MySQL系列之十三
    备份与恢复:MySQL系列之十二
    日志记录:MySQL系列之十一
    事务隔离实现并发控制:MySQL系列之十
    SpringMVC上传文件(图片)并保存到本地
    W10如何开启LinuxBash及安装Ubuntu
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/10670397.html
Copyright © 2020-2023  润新知