Socket UDP (Connexion routable)

Socket UDP (Connexion routable) - Divers - Programmation

Marsh Posté le 18-05-2004 à 21:42:04    

Bonjour à tous, voila j'ai un problème avec nos amis les sockets ^^ :
 
Introduction
J'ai fait un système 'client-serveur' basé sur le protocole UDP. un client se connecte sur un port prédéfini sur le serveur et dialogue avec lui, bien sur plusieurs clients peuvent se connecter en même temps sur le même serveur.
Une contrainte est que les paquets du serveur au client doivent passer un routeur (passerelle), pour cela il faut utiliser un seul socket pour la communication (ce qui est logique). Le fait d'utiliser un seul socket permet d'utiliser le même port en entrée et en sortie -> routable.
 
voici ce que cela donne (exemple avec des ports clients fictifs) :
 
http://pifou.myftp.org/~bordel/communication_client_serveur.gif
 
Le problème
Cela fonctionne relativement bien mais il y a un hic, lorsque un des client se déconnecte le socket devient inutilisable et ne peux plus écouter sur le port 54321, ce problème ne survient qu'en local et pas lorsque la connexion passe par un routeur.
 
 
Le code
Voila des parties de mon code (Ruby) avec explications :
 
Création du socket et écoute d'un nouveau message (peut provenir de n'importe quel utilisateur) :

s = UDPSocket::new
s.bind('', 54321)
while true
   packet = s.recvfrom(255)
 
   #traitement du packet, par exemple envois au client de données :
   s.send("données", 0, packet[1][3], packet[1][1])
end


 
Dans un autre thread le serveur envois des données à chaque client connecté (au travers du même thread) :

begin
   @s.send("données", 0, @ip, @port)
rescue
   puts "A player is disconnected"  
end


 
Voila, est-ce que qqun à une solution à mon problème ?
 
Merci d'avance !


Message édité par Ummon le 18-05-2004 à 21:42:32
Reply

Marsh Posté le 18-05-2004 à 21:42:04   

Reply

Marsh Posté le 18-05-2004 à 22:47:13    

l'UDP n'est pas connecté.
 
je vois pas comment un client A qui se déconnecte fait perdre la socket de la machine B (puisqu'il ne le sait pas)

Reply

Marsh Posté le 18-05-2004 à 23:34:59    

bjone> l'UDP n'est pas connecté.
 
Je parle de "connexion" lorsque il n'y a que 2 ports pour le communication en tout (un coté serveur et l'autre coté client), un socket est par définition une communication connecté donc parler de "socket udp" est un abus de langage... mais ce n'est pas le débat ici.
 
 
bjone> je vois pas comment un client A qui se déconnecte fait perdre la socket de la machine B (puisqu'il ne le sait pas)
 
Je me pose moi même la question...  

Reply

Marsh Posté le 19-05-2004 à 01:36:18    

je soupsonne plus un problème de persistance de tes objets liée à ton code et/ou une subtilitée de ruby...
 
peut être tu devrais tester plusieures approche de code pour voir si y'a un beans à ce niveau....

Reply

Marsh Posté le 19-05-2004 à 08:48:11    

Non , en fait voila le message d'erreur que je recoit :
 
WSAECONNRESET : The virtual circuit was reset by the remote side executing a hard or abortive close. For UPD sockets, the remote host was unable to deliver a previously sent UDP datagram and responded with a "Port Unreachable" ICMP packet. The application should close the socket as it is no longer usable.
 
Voila pourquoi l'erreur n'apparait pas en passant pas un routeur : le paquet 'ICMP' n'est pas routé.
 
Mais bon ca ne résoud pas mon problème :(, J'ai beau trapper l'erreur Ruby me détruit mon socket ! ouhin


Message édité par Ummon le 19-05-2004 à 09:10:37
Reply

Marsh Posté le 19-05-2004 à 10:42:20    

Voici un code d'exemple de ce que je veux faire, essayez de lancer le serveur puis d'y connecter un client et de le déconnecter. une erreur va apparaitre sur le serveur et casser le socket :

server.rb:12:in `recvfrom': An existing connection was forcibly closed by the re
mote host. - recvfrom(2) (Errno::ECONNRESET)


 
Mon but est de simplement ignorer ce message et de faire en sorte que le socke ne se détruise pas.
Dans l'exemple rien n'est prévu si un client se déconnecte, il y a normalement une variable qui compte le temps d'inactivité du client en fonction des paquets recut mais je ne l'ai pas mi pour des raisons de lisibilité.
 
 
server.rb :

#!/usr/bin/ruby
#server
 
require 'socket'
 
s = UDPSocket::new
s.bind('', 54321)
 
connected_client = Array::new
 
while true
   packet = s.recvfrom(255)
   
   if packet[0] == 'init'
      new_num_client = rand(1000)
      s.send(new_num_client.to_s, 0, packet[1][3], packet[1][1])
      connected_client.push(new_num_client)
       
      Thread::new(s, packet[0], packet[1][3], packet[1][1]){|s, data, ip, port|
         puts "A new client connected"
         while true
            sleep(1.0)
            s.send("server data", 0, ip, port)
         end
      }
   else
      data = packet[0].split('|')
      puts "according to data #{data[1]} from client #{data[1]} change some state of the server"
   end
end
 


 
client.rb :

#!/usr/bin/ruby
#client
 
require 'socket'
 
s = UDPSocket::new
s.connect('localhost',  54321)
s.send('init', 0)
packet = s.recvfrom(255)
my_num = packet[0].to_i
   
Thread::new{
   while true
      s.send("#{my_num}|client data : #{$*[0]}", 0)
      sleep(0.5)
   end
}
 
while true
   packet = s.recvfrom(255)
   puts "I received server data : #{packet[0]}"
end


Message édité par Ummon le 19-05-2004 à 11:54:22
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed