2009-05-28 11 views
1

J'ai rencontré un problème avec un serveur réseau qui reçoit les signaux des périphériques produits par ma société. L'appareil réutilisera occasionnellement le port source qu'il vient d'utiliser. Cela provoque la suppression du SYN par le serveur. Le périphérique réessaye alors jusqu'à ce que l'ancien socket tombe de TIME_WAIT sur le serveur. Le serveur puis SYN-ACKs.Serveur réseau Java et TIME_WAIT

Le serveur est écrit en Java. Malheureusement, il n'est pas possible de modifier correctement le périphérique pour faire passer les ports correctement, car ils sont nombreux sur le terrain et la mise à jour des unités existantes n'est pas une option. L'ancien logiciel a été écrit en C++ et a effacé le port TIME_WAIT de la liste dans la pile TCP de Windows.

Quelqu'un peut-il me donner des conseils sur la façon de contourner TIME_WAIT de Java sur Windows?

EDIT: J'ai effectivement confirmé dans Wireshark que le périphérique réutilisait un port récemment utilisé.

Sur le socket serveur J'utilise les options suivantes:

socket = new ServerSocket(); 
socket.setPerformancePreferences(3, 2, 1); 
socket.setReuseAddress(true); 
socket.setSoTimeout(CLIENT_READ_TIMEOUT); 
socket.bind(new InetSocketAddress(group.getPort()), MAX_TCP_BACKLOG); 

et la prise en charge client a ce qui suit fixé après réception:

Socket client = server.accept(); 
client.setKeepAlive(false); 
client.setSoLinger(true, 0); 
client.setReuseAddress(true); 
client.setTcpNoDelay(true); 
client.setSoTimeout(CLIENT_READ_TIMEOUT); 

J'ai essayé SO_LINGER à la fois vrai et faux, avec exactement les mêmes résultats de trace. CLIENT_READ_TIMEOUT est défini sur 10 secondes.

Répondre

3

Le vieux pas recommandé astuce pour éviter TIME_WAIT est de définir l'option de prise SO_LINGER-{ 1, 0 } - le close envoie alors RST au lieu de faire séquence d'échange normale de chasse/quatre voies, évitant ainsi la TIME_WAIT tous ensemble (attention - Vous pourriez perdre la queue de ce que vous avez encore dans le tampon d'envoi.) Je ne peux pas commenter si cela pourrait être fait en Java cependant.

EDIT: Pouvez-vous confirmer avec tcpdump que les clients réutilisent réellement les numéros de port source? Si ce n'est pas le cas, cela pourrait être le cas classique de l'option de socket d'écoute SO_REUSEADDR, comme Jon l'a souligné.

4

Miser sur la réponse de Nikolai,

Socket s; 
... 
s.setSoLinger(true,0); 

serait l'équivalent en Java.

EDIT: Une autre chose que vous pourriez vouloir regarder serait setReuseAddress (true);

0

Le serveur ignore les paquets SYN du client car il ne peut pas faire la distinction entre ceux d'une nouvelle session utilisant l'ancien port source et les retransmissions de l'ancienne session. Si vous contournez l'état TIME_WAIT sur le serveur, en définissant l'intervalle de temporisation système pour l'expiration des entrées d'état TIME_WAIT dans la table des blocs de contrôle, comment votre serveur ignore-t-il correctement les retransmissions SYN pour les sessions déjà terminées?

Questions connexes