Définition d'un délai d'expiration pour les opérations de socket

86

Lorsque je crée une socket:

Socket socket = new Socket(ipAddress, port);

Il lève une exception, ce qui est OK, car l'adresse IP n'est pas disponible. (Les variables de test où String ipAddress = "192.168.0.3"et int port = 300.)

Le problème est le suivant: comment le définir sur timeout pour cette socket?

Lorsque je crée le socket, comment puis-je réduire le temps avant que j'obtienne un UnknownHostExceptionet que le socket expire?

Jennifer
la source
10
@adrianboimvaser: Dans ce cas, vous devez marquer comme doublon et laisser un commentaire pointant vers le duplicata, afin qu'un modérateur puisse le fermer comme tel (vous avez laissé ce commentaire il y a un an - peut-être que vous le savez maintenant). Je voterais pour cela maintenant, mais je n'ai aucune idée de l'endroit où se trouve le double!
Tom Anderson
1
Pour continuer la tendance à répondre des années en retard, @EJP le titre de cette question est beaucoup moins ambigu que le doublon que vous avez suggéré
Isaac
@Isaac Et en fait ce n'est pas du tout un doublon, commentaire rétracté.
Marquis of Lorne
(Remarque: j'ai modifié le titre pour qu'il soit moins ambigu.)
Stephen C

Réponses:

165

Utilisez plutôt le Socket()constructeur et la connect(SocketAddress endpoint, int timeout)méthode .

Dans votre cas, cela ressemblerait à quelque chose comme:

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

Citant la documentation

connect

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

Connecte ce socket au serveur avec une valeur de délai d'expiration spécifiée. Un timeout de zéro est interprété comme un timeout infini. La connexion se bloquera alors jusqu'à ce qu'elle soit établie ou qu'une erreur se produise.

Paramètres:

endpoint- le SocketAddress
timeout- la valeur du délai d'expiration à utiliser en millisecondes.

Jette:

IOException- si une erreur se produit pendant la connexion
SocketTimeoutException- si le délai expire avant la connexion
IllegalBlockingModeException- si cette socket a un canal associé et que le canal est en mode non bloquant
IllegalArgumentException- si le point de terminaison est nul ou est une sous-classe SocketAddress non prise en charge par cette socket

Depuis: 1.4

aioobe
la source
4
Cela peut réduire le délai d'expiration de ConnectException (mais pas l'augmenter), et cela n'a aucun effet sur le délai d'expiration pour UnknownHostException, que l'OP prétend obtenir (bien que je ne le crois pas). Notez également que le Javadoc est incorrect en déclarant que la valeur par défaut est l'infini. Ça ne l'est pas. La plate-forme a un délai d'expiration par défaut d'environ une minute, et cela ne peut pas être augmenté.
Marquis de Lorne
3
Même après 4 ans, cela a été utile, cela devrait être la réponse acceptée.
Sharp Edge
4
Cela fait maintenant 5 ans et c'est la meilleure réponse que j'ai trouvée sur Internet .. Merci
MBH
1
Il est également important d'appeler socket.setSoTimeout(timeoutMillis)des délais d'expiration lors du blocage des opérations d'E / S.
Gray
43

Vous ne définissez pas de délai pour le socket, vous définissez un délai pour les opérations que vous effectuez sur ce socket.

Par exemple socket.connect(otherAddress, timeout)

Ou socket.setSoTimeout(timeout)pour définir un délai d'expiration des read()opérations.

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

payne
la source
Eh bien, dans ce cas, c'est aussi une opération de connexion. Je ne trouve aucun endroit qui indique que ce processeur utilise un délai d'attente infini bien que cela semble être le cas.
sandos
3
@sandos C'est clairement indiqué dans le Javadoc pour connect (). Cependant, il est également incorrect. Le délai d'expiration par défaut est le délai d'expiration de la plate-forme, environ une minute, pas l'infini, et il ne peut être réduit que par cette méthode connect (), pas augmenté.
Marquis de Lorne
note, socket.setSoTimeoutdoit être appelé APRÈS connect, ou il n'aura aucun effet et les lectures ne seront jamais expirées. c'est un piège mal documenté.
pstanton le
19

Vous pouvez utiliser la solution suivante:

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

J'espère que cela aide!

récif
la source
1
Si, comme il le prétend, il obtient une UnknownHostException, cela se produira sur la première ligne, où aucun délai d'expiration modifié n'est en vigueur.
Marquis de Lorne
Cependant, la première ligne ne lève aucune exception. De la documentation: « Une tentative sera faite pour résoudre le nom d' hôte dans un InetAddress Si cette tentative échoue, l'adresse sera marquée comme non résolue. »
Ady
Dans ce cas, il sera résolu par la connect()méthode, mais pas sous le contrôle d'un délai d'attente.
Marquis of Lorne
8

Vous ne pouvez pas contrôler le délai en raison de UnknownHostException. Ce sont des horaires DNS. Vous ne pouvez contrôler le délai de connexion que pour un hôte valide. Aucune des réponses précédentes n'aborde correctement ce point.

Mais j'ai du mal à croire que vous obtenez vraiment un UnknownHostExceptionlorsque vous spécifiez une adresse IP plutôt qu'un nom d'hôte.

EDIT Pour contrôler les délais d'expiration DNS de Java, consultez cette réponse .

Marquis de Lorne
la source