Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Probleme de communication entre client-serveur en Java

5 réponses
Avatar
adabla
Bonjour,

J'ai un soucis avec mon application client serveur en Java.

Voila c'est une application de tchat, en java, en utilisation les socket datagramme (DatagramSocket):

-Le serveur est à l'écoute d'un port
-le client possède une zone de texte pour son pseudo et un bouton pour s'enregistrer avant de dialoguer. Une fois qu'il valide le bouton d'enregistrement, son pseudo est envoyé au serveur via un DatagramPacket. Le serveur l'enregistre simplement sans message de retour et enregistre aussi l'adresse et le port du client
-Puis le client peut écrire le texte qu'il veut et l'envoyer à un autre client enregistré sur le tchat

Tout ce passe bien en local et tout fonctionne correctement. Nous avons testé plusieurs fois sur le réseau local (en 192.168.0.0/24) et on arrive à s’écrire et à s'envoyer des messages. Vraiment tout est ok. Le problème se passe une fois l'application déployée en ligne.
Une fois déployé, nous avons pris soin de changer l'adresse du serveur au niveau des clients et on utilise l'adresse publique du serveur maintenant.

Via des logs (println) sur le serveur, je me rends compte que le serveur reçoit bien les messages clients, mais une fois ces messages relayés au client destinataire, il ne reçoit rien. Lorsqu'on essai à nouveau en local, ça marche bien, mais une fois le serveur déployé, il reçoit les messages mais ne relaie pas ces messages.

Mon hypothèse est la suivante:
-puisque le serveur utilise l'adresse du client enregistrée lors de l'inscription du client, j'ai alors affiché sur le serveur cette adresse et c'est l'adresse publique de notre connexion internet (et pas l'adresse du sous réseau local du client qui est 192.168.0.0/24) . et je me dis que quand le serveur relaie le message, c'est à cette adresse publique+port qu'il relaie et le message ne parvient donc pas à l'émetteur.

Si mon hypothèse est bonne, alors comment régler cela? sinon si une personne comprend la cause du problème, je le remercie de partager son expérience pour le résoudre. Dans tous les cas, toutes vos hypothèses et solutions sont les bienvenues.

Merci merci

(PS: informations pouvant être utiles

-j'utilise simplement un DatagramPacket et DatagramSocket pour la connexion et l'envoi des packets réseau
-le serveur enregistre les pseudo des clients via un message formaté et aussi leur adresse IP+PORT en les extrayant du datagramPacket venant des clients
-une fois déployé, nous avons pris soin de modifier l'adresse du serveur que le client utilisait, en remplaçant par l'adresse publique du serveur
-client et serveur sont des applications Java lourd

5 réponses

Avatar
Yliur
Le Tue, 02 Feb 2021 05:11:15 -0600, adabla a écrit :
Mon hypothèse est la suivante:
-puisque le serveur utilise l'adresse du client enregistrée lors de
l'inscription du client, j'ai alors affiché sur le serveur cette adresse
et c'est l'adresse publique de notre connexion internet (et pas
l'adresse du sous réseau local du client qui est 192.168.0.0/24) . et je
me dis que quand le serveur relaie le message, c'est Í  cette adresse
publique+port qu'il relaie et le message ne parvient donc pas Í 
l'émetteur.
Si mon hypothèse est bonne, alors comment régler cela? sinon si une
personne comprend la cause du problème, je le remercie de partager son
expérience pour le résoudre. Dans tous les cas, toutes vos hypothèses et
solutions sont les bienvenues.

Si je comprends bien, tu as un serveur sur une machine publique et un
client sur une machine qui se trouve sur un réseau privé, cachée derrière
une machine avec une adresse publique.
Si le serveur maintient la connexion avec le client et répond dedans, je
pense que ça peut fonctionner. Sinon je pense qu'il n'y a pas moyen de
joindre facilement la machine qui a une adresse privée sur le réseau.
L'adresse publique + port n'est valable que pour la connexion initiale
entre le client et le serveur, mais ne permet pas de joindre le client Í 
nouveau plus tard.
Il me semble qu'il existe des méthodes plus complexes pour permettre Í 
des machines ayant des adresses privées de communiquer, tu peux demander
sur un groupe de réseau. Mais si tu cherches une solution simple, le
mieux serait sans doute de maintenir la connexion initiale ouverte : elle
est sans doute Í  double sens, le serveur peut répondre dedans, non ? Il
n'y a pas besoin de créer une connexion pour chaque message.
Avatar
Olivier Miakinen
Bonjour,
Le 03/02/2021 02:40, Yliur répondait Í  adabla :
[...]

Si je comprends bien, tu as un serveur sur une machine publique et un
client sur une machine qui se trouve sur un réseau privé, cachée derrière
une machine avec une adresse publique.

C'est ce que je comprends aussi. Avec une traduction d'adresse (NAT) par le
routeur : <https://fr.wikipedia.org/wiki/Network_address_translation&gt;.
[...] Mais si tu cherches une solution simple, le
mieux serait sans doute de maintenir la connexion initiale ouverte : elle
est sans doute Í  double sens, le serveur peut répondre dedans, non ? Il
n'y a pas besoin de créer une connexion pour chaque message.

Oui. Et c'est la solution en charte sur fr.comp.lang.java.
Une solution plus compliquée consisterait Í  configurer le routeur de telle
sorte que les paquets lui arrivant sur un port TCP ou UDP Í  configurer
soient retransmis Í  l'adresse de la machine locale. Mais lÍ  ce serait en
charte sur un groupe tel que fr.comp.reseaux.ip plutÍ´t qu'ici.
--
Olivier Miakinen
Avatar
Yliur
Le Wed, 03 Feb 2021 08:30:30 +0100, Olivier Miakinen a écrit :
Une solution plus compliquée consisterait Í  configurer le routeur de
telle sorte que les paquets lui arrivant sur un port TCP ou UDP Í 
configurer soient retransmis Í  l'adresse de la machine locale. Mais lÍ 
ce serait en charte sur un groupe tel que fr.comp.reseaux.ip plutÍ´t
qu'ici.

Oui. J'ai surtout peur que ça ne corresponde pas au problème d'origine
(bien qu'on n'en sache pas assez) : il faut configurer le routeur pour
chaque client qui veut se connecter au serveur, j'imagine que ce n'est
pas l'idée d'un client de discussion en ligne.
Avatar
Olivier Miakinen
Le 03/02/2021 22:07, Yliur a écrit :
[bidouille NAT]

Oui. J'ai surtout peur que ça ne corresponde pas au problème d'origine
(bien qu'on n'en sache pas assez) : il faut configurer le routeur pour
chaque client qui veut se connecter au serveur, j'imagine que ce n'est
pas l'idée d'un client de discussion en ligne.

Exact.
--
Olivier Miakinen
Avatar
David Larochette
Le 02/02/2021 Í  12:11, adabla a écrit :
Mon hypothèse est la suivante:
-puisque le serveur utilise l'adresse du client enregistrée lors de
l'inscription du client, j'ai alors affiché sur le serveur cette adresse et
c'est l'adresse publique de notre connexion internet (et pas l'adresse du sous
réseau local du client qui est 192.168.0.0/24) . et je me dis que quand le
serveur relaie le message, c'est Í  cette adresse publique+port qu'il relaie et
le message ne parvient donc pas Í  l'émetteur.
Si mon hypothèse est bonne, alors comment régler cela? sinon si une personne
comprend la cause du problème, je le remercie de partager son expérience pour le
résoudre. Dans tous les cas, toutes vos hypothèses et solutions sont les
bienvenues.

La solution la plus simple Í  mon avis est d'utiliser une pile UPnP pour
créer une redirection de port sur ton routeur (Í  condition qu'il
supporte UPnP, la quasi-totlité des boxs internet le font).
En Java, tu peux utiliser une librairie telle que Cling ou WaifUPnP.
Par exemple avec Waif ça donne :
com.dosse.upnp.UPnP.openPortUDP(MON_PORT)
qui renvoie true si un routeur UPnP a été détecté, le port a été ouvert
et une redirection créée.