Почему inet: /0.0.0.0 интерпретируется как comet: / 0: 0: 0: 0: 0: 0: 0: 0 com.sun.net.httpserver.HttpServer? - PullRequest
4 голосов
/ 28 октября 2010

Мы обнаружили эту проблему при реализации логики переподключения для конечной точки WS с использованием стека JAX-WS, развернутого на сервере Glassfishv2.1. Развертываем веб-сервис в кластерной среде. Чтобы упростить развертывание, мы используем 0.0.0.0 в качестве IP-адреса, на котором необходимо опубликовать конечную точку, чтобы к ней можно было получить доступ со всех доступных IP-адресов, относящихся к узлам кластера. Ниже приведен фрагмент кода для инициализации WS (веб-службы):

 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");

Мы вызываем receive.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 зависит от InetSocketAddress HttpServer, который прослушивает ip: порт URL-адреса, где публикуется конечная точка WS, для получения некоторой информации о состоянии из карта. Поскольку адрес inet "inet: /0.0.0.0" интерпретируется как "inet: / 0: 0: 0: 0: 0: 0: 0: 0", он не может найти запись на карте и, следовательно, NPE. Вот исходный код ServerMgr.

Чтобы доказать, что это действительно проблема, мы попытались воспроизвести логику кода ServerMgr, связанного с InetSocketAddress, в виде следующей программы:

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

и следующий вывод на моем устройстве dev (Linux Tahoe 2.6.9-67.EL # 1 Ср 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 в качестве конечной точки адрес, поскольку это упрощает развертывание нашего веб-сервиса)

Ответы [ 2 ]

3 голосов
/ 02 марта 2012

Вы можете заменить 0.0.0.0 на InetAddress.getLocalHost().getHostAddress(); Он будет автоматически разрешен правильно и нет необходимости -Djava.net.preferIPv4Stack=true

0 голосов
/ 28 октября 2010

Вы пытались принудительно выбрать IPv4 как переменную для исполняемого файла Java?

-Djava.net.preferIPv4Stack=true

Взгляните здесь и здесь ..

Также возможно принудительно использовать IPv4 из вашего кода с помощью System.setProperty("java.net.preferIPv4Stack" , "true");

...