2016-04-11 24 views
1

Ich bin eine Buchse zurück von ServerSocket.accept()-SSLSocket mit dem folgenden Code ein Upgrade:Warum java SSLSocketImpl erstellt einen Dummy-Socket?

SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket (socket, null, true); 
sslSocket.setUseClientMode (false); 
sslSocket.setSSLParameters (sslParameters); 

Nachdem ich sslSocket.close() Ich kann sehen, dass einige offene Dateideskriptor sind auf dem Server zurückgelassen. Diese zeigen sich in lsof Ausgabe wie folgt:

292u sock    0,6  0t0 73633829 can't identify protocol 

Im Laufe der Zeit (da dies ein Server) und Client macht viele Verbindungen diese offenen Dateien zu verhindern, neue Verbindungen nicht passiert.

Ich habe versucht, die Ursache dafür zu finden, da das Problem nicht aus unserem Code zu generieren scheint, indem wir Openjdk-Code betrachten. Ich kann sehen, dass während SSLSocket Schließen der folgende Code Fluss auftritt:

SSLSocketImpl der Nähe -> closeInternal (true) -> Close (true)

Es folgt der Code von Close:

if (!isLayered() || autoClose) { 
    super.close(); 
} else if (selfInitiated) { 
    // layered && non-autoclose 
    // read close_notify alert to clear input stream 
    waitForClose(false); 
} 

Seit es ist geschichtet und autoClose ist wahr, ich denke, es geht in super.close(). Im Folgenden ist der Code für eine enge Funktion von Superklasse:

public synchronized void close() throws IOException { 
    if (self == this) { 
     super.close(); 
    } else { 
     self.close(); 
    } 
} 

Also, da selbst = dies, self.close() aufgerufen wird!. Was bedeutet, dass der "Dummy" Socket, der intern von SSLSocket erstellt wird, niemals geschlossen wird.

Erstens, habe ich Recht in dieser Analyse, dass der interne Socket von SSLSocket immer nicht geschlossen ist? Ist das ein Fehler in Java oder ist mein Verständnis falsch oder mache ich etwas falsch?

Edit: (weitere Erläuterungen, Fragen zu beantworten)

Selbst ist von OpenJDK Code nur (speziell BaseSSLSocektImpl.java). Lassen Sie mich einige relevante Code einfügen, die hoffentlich verdeutlicht:

final public class SSLSocketImpl extends BaseSSLSocketImpl { 
    SSLSocketImpl(SSLContextImpl context, Socket sock, 
      InputStream consumed, boolean autoClose) throws IOException { 
     super(sock, consumed); 
     // We always layer over a connected socket 
     if (!sock.isConnected()) { 
      throw new SocketException("Underlying socket is not connected"); 
     } 

     // In server mode, it is not necessary to set host and serverNames. 
     // Otherwise, would require a reverse DNS lookup to get the hostname. 

     init(context, true); 
     this.autoClose = autoClose; 
     doneConnect(); 
    } 
//.... 
} 

abstract class BaseSSLSocketImpl extends SSLSocket {  

    final private Socket self; 

    BaseSSLSocketImpl(Socket socket) { 
     super(); 
     this.self = socket; 
     this.consumedInput = null; 
    } 

// .... 
} 

"Dummy" socket:

public abstract class SSLSocket extends Socket 
{ 
    protected SSLSocket() 
     { super(); } 

// ... 
} 

class Socket implements java.io.Closeable { 
    public Socket() { 
     setImpl(); 
    } 
// This is what I am calling dummy socket which is getting created 

    void setImpl() { 
     if (factory != null) { 
      impl = factory.createSocketImpl(); 
      checkOldImpl(); 
     } else { 
      impl = new SocksSocketImpl(); 
     } 
     if (impl != null) 
      impl.setSocket(this); 
    } 
} 

class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { 
// ... 
}} 

So intern ein SocksSocketImpl Objekt geschaffen, die Buchse erzeugt (die ich als Dummy beziehen sich auf Socket für das bessere Wort) in nativem Code.

+0

Was ist Selbst?'Was bedeutet, dass der" dummy "Socket, der intern von SSLSocket erstellt wurde, nie geschlossen wird. --- Was meinst du damit? –

+0

@Am_I_Hilfful Ich habe dem ursprünglichen Post eine Erläuterung hinzugefügt. Bitte lassen Sie mich wissen, wenn es noch etwas Verwirrung gibt. – Prabhat

Antwort

0

Ein SSLSocket kann Ether von Grund auf neu erstellt oder über eine bestehende Socket, über SSLSocketFactory.craeteSocket(Socket, ...) geschichtet werden. Die Komplikation im Code tritt auf, um beide Fälle zu behandeln. Manchmal die SSLSocket muss sich selbst schließen, manchmal die eingewickelte Socket, und manchmal auch nicht, je nachdem, ob es umwickelt oder nicht, und wenn verpackt, ob autoClose war wahr.