163 votes

Comment puis-je interrompre la méthode accept() d'une ServerSocket ?

Dans mon fil principal, j'ai un while(listening) qui appelle accept() sur mon ServerSocket puis lance un nouveau fil client et l'ajoute à une collection lorsqu'un nouveau client est accepté.

J'ai également un fil de discussion pour l'administration que je veux utiliser pour donner des ordres, par exemple 'exit' qui provoquera l'arrêt de tous les threads du client, s'arrêtera lui-même et arrêtera le thread principal, en mettant l'écoute à false.

Cependant, le accept() dans l'appel while(listening) La boucle se bloque, et il ne semble pas y avoir de moyen de l'interrompre, de sorte que la condition "while" ne peut pas être vérifiée à nouveau et que le programme ne peut pas sortir !

Y a-t-il une meilleure façon de procéder ? Ou un moyen d'interrompre la méthode de blocage ?

1 votes

0 votes

Pour les personnes qui veulent attendre x temps et ensuite réagir, utilisez setSoTimeout().

177voto

Simon Groenewolt Points 7046

2 votes

Merci, c'est tellement évident, ça ne m'a même pas traversé l'esprit ! J'appelais close() après être sorti de la boucle.

4 votes

Il est étrange qu'il n'y ait pas cette information dans la documentation : download.oracle.com/javase/6/docs/api/java/net/ n'est pas marquée comme produisant une SocketException. Elle est seulement mentionnée ici download.oracle.com/javase/1.4.2/docs/api/java/net/

1 votes

Est-ce que je peux appeler close() Je veux dire qu'il lèvera une exception en le faisant, alors y a-t-il une autre façon (qui ne lève pas d'exception, et qui n'est pas basée sur le délai d'attente) d'arrêter d'écouter les demandes ?

33voto

Juha Syrjälä Points 11475

Définir le délai d'attente sur accept() l'appel sera interrompu après le temps spécifié :

http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT

Définir un délai d'attente pour le blocage Socket opérations :

ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();

L'option doit être définie avant d'entrer dans une opération de blocage pour prendre effet. Si le délai d'attente expire et que l'opération continue à se bloquer, java.io.InterruptedIOException est soulevée. Le site Socket n'est pas fermé dans ce cas.

11voto

Lauri Lehtinen Points 5417

Appelle close() sur le ServerSocket une option ?

http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29

Ferme cette prise. Tout thread actuellement bloqué dans accept() lèvera une SocketException.

3voto

Soham Malakar Points 46

La raison ServerSocket.close() lance un exception c'est parce que vous avez un outputstream ou un inputstream attaché à cette prise. Vous pouvez éviter cette exception en toute sécurité en fermant d'abord les flux d'entrée et de sortie. Ensuite, essayez de fermer le ServerSocket . Voici un exemple :

void closeServer() throws IOException {
  try {
    if (outputstream != null)
      outputstream.close();
    if (inputstream != null)
      inputstream.close();
  } catch (IOException e1) {
    e1.printStackTrace();
  }
  if (!serversock.isClosed())
    serversock.close();
  }
}

Vous pouvez appeler cette méthode pour fermer n'importe quelle socket de n'importe où sans obtenir une exception.

9 votes

Les flux d'entrée et de sortie ne sont pas attachés à l'interface utilisateur. ServerSocket mais à un Socket et nous parlons de fermer le ServerSocket pas le Socket donc le ServerSocket peut être fermé sans fermer un Socket Les flux de l'entreprise.

0voto

stu Points 2216

Une autre chose que vous pouvez essayer, et qui est plus propre, est de vérifier un drapeau dans la boucle accept, et ensuite, lorsque votre thread d'administration veut tuer le thread qui bloque sur l'accept, mettez le drapeau (rendez-le sûr pour les threads) et ensuite faites une connexion de socket client au socket d'écoute. L'accept cessera de bloquer et retournera le nouveau socket. Vous pouvez élaborer un protocole simple indiquant au thread d'écoute de quitter le thread proprement. Et ensuite, fermez le socket du côté client. Pas d'exceptions, beaucoup plus propre.

0 votes

Cela n'a aucun sens ... lorsque vous avez un code comme celui-ci socket = serverSocket.accept() ; à ce moment, le blocage commence et la boucle ne fait pas partie de notre code, il y a donc un moyen de faire en sorte que ce code bloquant recherche un drapeau que j'ai défini ... du moins, je n'ai pas été en mesure de trouver un moyen de le faire ... si vous avez un code fonctionnel, veuillez le partager ?

0 votes

Oui, il semblerait que j'aie omis une information cruciale qui ferait que ça n'aurait pas beaucoup de sens. Il faudrait que le socket d'acceptation ne soit pas bloquant et qu'il ne soit bloqué que pendant un certain temps avant que la boucle ne se répète, auquel cas il faudrait vérifier le drapeau de sortie.

0 votes

Comment, exactement, faire en sorte que la prise d'acceptation soit non bloquante ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X