2013-05-16 15 views
6

Jak zapobiec wiązaniu aplikacji Java z gniazdem, do którego inny proces jest już powiązany w systemie Windows?Zapobieganie powiązaniu aplikacji z gniazdem, które jest już powiązane

Mam problem z aplikacją Java, która nasłuchuje na porcie 80. Aplikacja zaczyna działać poprawnie i nie zgłasza żadnych wyjątków. Nie mogłem się domyślić, dlaczego nie mogłem połączyć się z portem 80. Inne porty działały dobrze. Sprawdziłem netstat dla innych procesów nasłuchujących na 80 i znalazłem Skype'a. Nie sądziłem, że to możliwe, ale po pewnych badaniach przypuszczam, że Skype nasłuchuje z opcją SO_REUSEADDR. W tym stanie aplikacja akceptująca jest nieokreślona. Chciałbym, aby moja aplikacja Java nie działała w tym przypadku z wyjątkiem wiązania (lub innym).

Wygląda na to, że mógłbym użyć SO_EXCLUSIVEADDRUSE, gdybym miał dostęp do tej opcji przez Javę, ale nie sądzę, że jest to możliwe. Wokół SO_REUSEADDR jest wiele pytań i odpowiedzi, ale nie znalazłem odpowiedzi na moje pytanie. Nie chodzi tylko o Skype (mogę wyłączyć słuchanie), chcę, aby mój program był bardziej solidny w tej sytuacji.

Jest to urywek z netstat -abn na Windows 7 pudełka:

Proto Local Address   Foreign Address  State 
    TCP 0.0.0.0:80    0.0.0.0:0    LISTENING [java.exe] 
    TCP 0.0.0.0:80    0.0.0.0:0    LISTENING [Skype.exe] 

Dlatego jestem przy założeniu, że Skype wykorzystuje SO_REUSEADDR

Procesy nie wydają się być na słuchanie różne interfejsy.

Oto fragment kodu. Port to 80:

myServerSocket = new ServerSocket(myTcpPort); 
    while (true) { 
     new HTTPSession(myServerSocket.accept(), threadPool); 
    } 

W ramach dalszych informacji stworzyłem przykładowy program, aby zminimalizować jakiekolwiek efekty uboczne lub niepoprawne wiadomości.

import java.net.ServerSocket; 

    public class PortTest 
    { 
     public static void main(String[] args) 
     { 
      System.out.println("Hit Ctrl-C to stop.\n"); 

      try { 
       ServerSocket myServerSocket = new ServerSocket(80); 
       System.out.println("Before the accept() call."); 
       myServerSocket.accept(); 
       System.out.println("After the accept() call."); 
      } 
      catch (Exception ex) { 
       System.out.println("Error listening."); 
       ex.printStackTrace(); 
      } 
     } 

    } 

ja nadal nie dostaniesz wyjątek, gdy uruchomiony program przykładowy (PortTest) i gdy Skype działa i nasłuchuje na porcie 80. I do dalszych badań, I wykonany drugą instancję PortTest a ja widzę komunikat port w użyciu.

Error listening. 
    java.net.BindException: Address already in use: JVM_Bind 
      at java.net.DualStackPlainSocketImpl.bind0(Native Method) 
      at java.net.DualStackPlainSocketImpl.socketBind(Unknown Source) 
      at java.net.AbstractPlainSocketImpl.bind(Unknown Source) 
      at java.net.PlainSocketImpl.bind(Unknown Source) 
      at java.net.ServerSocket.bind(Unknown Source) 
      at java.net.ServerSocket.<init>(Unknown Source) 
      at java.net.ServerSocket.<init>(Unknown Source) 
      at PortTest.main(PortTest.java:10) 
+2

Czy wiążą swoją ServerSocket do 0.0.0.0 adres? Może twój program Java nasłuchuje na porcie 80 na jednym IP i Skype na innym, wyjaśniając, dlaczego Java nie narzeka na wyjątek PortAlreadyInUse – gma

+0

GMA ma to prawo, po prostu wiąż na 0.0.0.0 i powinieneś dostać "kompletne" powiązanie lub wyjątek. –

+0

Czy możesz opublikować kod inicjujący ServerSocket? – gma

Odpowiedz

2
socket = new ServerSocket(0); 

automatycznie wybierze ci wolny port.

Ponadto ten kod powie pogoda port jest dostępna:

boolean portAvaliable = true; 
    ServerSocket s = null; 
    try { 
      s = new ServerSocket(yourPort); 
     } 
    catch (IOException e) 
     { 
      portAvaliable = false; 
     } 
    finally { 
     if (s != null) 
      try { 
       s.close(); 
       } 
      catch (IOException e) 
       { 
       //handle the exception 
       } 
+0

Muszę słuchać na określonym porcie, a nie losowo darmowym. Ponadto skutecznie robię to w moim kodzie. Jednak nie jest wyrzucany wyjątek, stąd mój problem. –

Powiązane problemy