Festlegen eines Zeitlimits für Socket-Vorgänge

85

Wenn ich einen Socket erstelle:

Socket socket = new Socket(ipAddress, port);

Es wird eine Ausnahme ausgelöst, die in Ordnung ist, da die IP-Adresse nicht verfügbar ist. (Die Testvariablen wo String ipAddress = "192.168.0.3"und int port = 300.)

Das Problem ist: Wie stelle ich das Timeout für diesen Socket ein?

Wie reduziere ich beim Erstellen des Sockets die Zeit, bevor ich einen erhalte, UnknownHostExceptionund stelle fest, dass der Socket eine Zeitüberschreitung aufweist?

Jennifer
quelle
10
@adrianboimvaser: In diesem Fall sollten Sie als Duplikat markieren und einen Kommentar hinterlassen, der auf das Duplikat verweist, damit ein Moderator es als solches schließen kann (Sie haben diesen Kommentar vor einem Jahr hinterlassen - vielleicht wissen Sie das jetzt). Ich würde jetzt meine Stimme dafür abgeben, aber ich habe keine Ahnung, wo das Duplikat ist!
Tom Anderson
1
Um den Trend fortzusetzen, Jahre zu spät zu antworten, ist der Titel dieser Frage bei @EJP viel weniger zweideutig als das von Ihnen vorgeschlagene Duplikat
Isaac
@Isaac Und in der Tat ist es überhaupt kein Duplikat, Kommentar zurückgezogen.
Marquis von Lorne
(Hinweis: Ich habe das Tittle so angepasst, dass es weniger mehrdeutig ist.)
Stephen C

Antworten:

163

Verwenden Sie stattdessen den Socket()Konstruktor und die connect(SocketAddress endpoint, int timeout)Methode .

In Ihrem Fall würde es ungefähr so ​​aussehen:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

Zitat aus der Dokumentation

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

Verbindet diesen Socket mit einem bestimmten Zeitlimitwert mit dem Server. Ein Timeout von Null wird als unendliches Timeout interpretiert. Die Verbindung wird dann blockiert, bis eine Verbindung hergestellt wurde oder ein Fehler auftritt.

Parameter:

endpoint- die SocketAddress
timeout- der Timeout-Wert, der in Millisekunden verwendet werden soll.

Würfe:

IOException- Wenn während der Verbindung ein Fehler auftritt
SocketTimeoutException- Wenn das Zeitlimit vor dem Herstellen der Verbindung abläuft
IllegalBlockingModeException- Wenn diesem Socket ein Kanal zugeordnet ist und sich der Kanal im nicht blockierenden Modus befindet
IllegalArgumentException- Wenn der Endpunkt null ist oder wenn eine SocketAddress-Unterklasse von diesem Socket nicht unterstützt wird

Seit: 1.4

aioobe
quelle
4
Dies kann das Zeitlimit für ConnectException verringern (aber nicht erhöhen) und hat keine Auswirkungen auf das Zeitlimit für UnknownHostException, das das OP angeblich erhält (obwohl ich es nicht glaube). Beachten Sie auch, dass der Javadoc nicht korrekt angibt, dass der Standardwert unendlich ist. Ist es nicht. Die Plattform hat ein Standardzeitlimit von ungefähr einer Minute, das nicht erhöht werden kann.
Marquis von Lorne
3
Auch nach 4 Jahren war dies hilfreich, dies sollte die akzeptierte Antwort sein.
Sharp Edge
4
Es ist jetzt nach 5 Jahren und es ist die beste Antwort, die ich im Internet gefunden habe. Danke
MBH
1
Es ist auch wichtig, socket.setSoTimeout(timeoutMillis)beim Blockieren von E / A-Vorgängen Zeitüberschreitungen zu fordern .
Grau
43

Sie legen kein Zeitlimit für den Socket fest, sondern ein Zeitlimit für die Vorgänge, die Sie an diesem Socket ausführen.

Beispielsweise socket.connect(otherAddress, timeout)

Oder socket.setSoTimeout(timeout)um ein Zeitlimit für read()Vorgänge festzulegen .

Siehe: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html

payne
quelle
Nun, in diesem Fall ist es auch eine Operation, die verbindet. Ich kann keinen Ort finden, der besagt, dass dieser Ctor eine unendliche Zeitüberschreitung verwendet, obwohl dies der Fall zu sein scheint.
Sandos
3
@sandos Es ist klar im Javadoc für connect () angegeben. Es ist jedoch auch falsch. Das Standardzeitlimit ist das Plattformzeitlimit von ungefähr einer Minute und nicht unendlich. Es kann nur durch diese connect () -Methode verringert und nicht erhöht werden.
Marquis von Lorne
Beachten Sie, socket.setSoTimeoutdass AFTER aufgerufen werden muss connect, da dies sonst keine Auswirkungen hat und das Lesen niemals abläuft. Dies ist eine schlecht dokumentierte Gotcha.
Pstanton
19

Sie können die folgende Lösung verwenden:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

Ich hoffe es hilft!

Riff
quelle
1
Wenn er, wie er behauptet, eine UnknownHostException erhält, geschieht dies in der ersten Zeile, in der kein geändertes Zeitlimit wirksam ist.
Marquis von Lorne
Die erste Zeile löst jedoch keine Ausnahme aus. Aus der Dokumentation: „wird versucht werden , die Hostnamen in eine InetAddress zu lösen Wenn dieser Versuch fehlschlägt, wird die Adresse als ungelöst gekennzeichnet werden.“
Ady
In diesem Fall wird es durch die connect()Methode behoben , jedoch nicht unter der Kontrolle eines Timeouts.
Marquis von Lorne
8

Sie können das Timeout aufgrund von nicht steuern UnknownHostException. Dies sind DNS-Timings. Sie können das Verbindungszeitlimit nur bei einem gültigen Host steuern. Keine der vorhergehenden Antworten spricht diesen Punkt richtig an.

Aber ich finde es schwer zu glauben, dass Sie wirklich eine bekommen, UnknownHostExceptionwenn Sie eine IP-Adresse anstelle eines Hostnamens angeben.

BEARBEITEN Um die DNS-Zeitüberschreitungen von Java zu steuern, lesen Sie diese Antwort .

Marquis von Lorne
quelle