为什么inet:/0.0.0.0被解释为inet:/ 0:0:0:0:0:0:0:0由com.sun.net.httpserver.HttpServer?

时间:2010-10-28 15:18:34

标签: java networking java-ee jax-ws ipv6

我们在使用部署在Glassfishv2.1服务器上的JAX-WS堆栈为WS端点实现重新连接逻辑时发现了这个问题。我们在集群环境中部署Web服务。为了简化部署,我们使用0.0.0.0作为端点需要发布的IP,以便可以从与集群节点相关的所有可用IP访问它。以下是用于初始化WS(Web服务)的代码片段:

 import javax.xml.ws.Endpoint;
 .
 .
 //Implementor is the corresponding implementation object for the WS
 Endpoint receiver = Endpoint.create(new Implementor());
 .
 receiver.setExecutor(threadPoolExecutor);
 receiver.publish ("http://0.0.0.0:9545/context");

我们调用receiver.stop()来停止在清理代码中发布端点。这就是我们收到带有以下堆栈跟踪的空指针异常的地方:

java.lang.NullPointerException
    at com.sun.xml.ws.transport.http.server.ServerMgr.removeContext(ServerMgr.java:123)
    at com.sun.xml.ws.transport.http.server.HttpEndpoint.stop(HttpEndpoint.java:110)
    at com.sun.xml.ws.transport.http.server.EndpointImpl.stop(EndpointImpl.java:167

在尝试查找NPE的原因时,我们发现ServerMgr类依赖于HttpServer的InetSocketAddress,它侦听发布WS端点的URL的ip:端口,以从中检索某些状态信息。地图。由于inet地址“inet:/0.0.0.0”被解释为“inet:/ 0:0:0:0:0:0:0:0”,因此无法在地图中找到条目,因此无法找到NPE。 Here is the source code of ServerMgr.

为了证明这实际上是问题所在,我们尝试将与InetSocketAddress相关的ServerMgr代码的逻辑复制为以下程序:

import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
static final String URL_1 = "http://0.0.0.0:9545/context";

static final String URL_2 = "http://127.0.0.1:9548/context";
static final String URL_3 = "http://10.226.90.217:9549/context";

public void testUrl(String address){
    try {
        URL url = new URL(address);
        Map<InetSocketAddress, Integer> map = new HashMap<InetSocketAddress, Integer>();

        InetSocketAddress iaddr = new InetSocketAddress(url.getHost(), url.getPort());
        map.put(iaddr, 1);

        HttpServer server = HttpServer.create(iaddr, 5);
        HttpContext context = server.createContext(url.toURI().getPath());
        server.start();
        System.out.println("original inet:"+iaddr+" and final inet:"+context.getServer().getAddress());
        if(iaddr.equals(context.getServer().getAddress())){
            System.out.println("equal");
            Integer t = map.get(context.getServer().getAddress());
            if( t == null){
                System.out.println("You won");
            }else{
                System.out.println("You lose "+t);
            }
        }else{
            System.out.println("not-equal");
        }
        server.stop(0);
        map.clear();

    } catch (URISyntaxException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}
public static void main(String[] args)
 {

  Main d = new Main();
  d.testUrl(Main.URL_1);
  d.testUrl(Main.URL_2);
  d.testUrl(Main.URL_3);


 }

}

奇怪的是,我在WindowsXP框(Java版本1.6.0_22)中获得了以下结果

 equal--
original inet:/0.0.0.0:9545 and final inet:/0.0.0.0:9545
equal
You lose 1
equal--
original inet:/127.0.0.1:9548 and final inet:/127.0.0.1:9548
equal
You lose 1
equal--
original inet:/10.226.92.47:9549 and final inet:/10.226.92.47:9549
equal
You lose 1

和我的开发框上的以下输出 (Linux tahoe 2.6.9-67.EL#1 Wed Nov 7 13:43:31 EST 2007 x86_64 x86_64 x86_64 GNU / Linux) (Java版本1.6.0_17)

run:
original inet:/0.0.0.0:9545 and final inet:/0:0:0:0:0:0:0:0:9545
not-equal
original inet:/127.0.0.1:9548 and final inet:/127.0.0.1:9548
equal
You lose 1
original inet:/10.226.90.217:9549 and final inet:/10.226.90.217:9549
equal
You lose 1

根据背景 - 我有两个问题:

  • 一个。为什么要解释0.0.0.0 作为IPv6地址? (另外,这是一个问题 与操作系统或JRE?这是一个错误 还是一个功能?等)
  • 湾我们有办法配置吗? JRE将0.0.0.0解释为IPv4地址? (我们希望继续使用0.0.0.0作为端点 地址,因为它简化了部署 我们的Web服务)

2 个答案:

答案 0 :(得分:3)

您可以将0.0.0.0替换为InetAddress.getLocalHost().getHostAddress(); 它会自动正确解析,不需要-Djava.net.preferIPv4Stack=true

答案 1 :(得分:0)

您是否曾尝试将IPv4选项强制作为java可执行文件的变量?

-Djava.net.preferIPv4Stack=true

看看herehere ..

也可以使用System.setProperty("java.net.preferIPv4Stack" , "true");

强制代码中的IPv4