IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

Sockets et Threads


Sujet :

Entrée/Sortie Java

  1. #1
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2016
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Sockets et Threads
    Bonjour à tous ,

    Je doit concevoir une application Java qui se doit de fonctionner en réseau à l'aide de Sockets et Threads.
    J'ai déjà expérimenté quelque tests de communication entre des clients connectés à l'aide de Sockets pour me familiariser avec et connaître leur fonctionnement.

    Mais l'étape bloquante pour moi est celle de communiquer entre 2 clients spécifiques connectés sur le même serveur.

    Comment faire pour que le serveur envoie à un client ce qu'il a reçu d'un autre client ?
    Il y a-t-il un moyen de changer le Socket au quel le serveur doit répondre ? De tel sorte qu'il ne répond pas a celui qui a écrit mais a un autre client.
    Comme on dit souvent, une image vaut mieux que 1'024 mots, voici un schéma de ma problématique :

    Nom : WhatsApp Image 2016-11-17 at 09.50.02 - copie.jpg
Affichages : 1419
Taille : 21,3 Ko

    Pour exemple, j'aimerais que le client A puisse communiquer uniquement avec le client G et inversement.

    Merci d'avance pour vos réponses

  2. #2
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    En général, ce qu'on fait, c'est ecouter sur un port coté serveur. Les clients se connectent à ce port et s'identifient (de maniere à ce que le serveur sache qui est A, B, ...). Ensuite, le serveur va faire la passerelle entre les clients qui doivent parler ensemble (typiquement, envoyer sur l'OutputStream de A ce qui vient de l'InputStream de G et inversement).
    Ce fonctionnement est assez commun car il permet d'eviter la configuration des routeurs/firewalls coté client (seul le serveur doit accepter les communications entrantes).

    La technique s'appelle le Hole Punching:
    https://en.wikipedia.org/wiki/Hole_p...g_(networking)

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Euh, le hole punching n'a rien à voir avec ça, c'est une technique pour tenter d'aider les clients à se connecter directement les uns aux autres, par des moyens plus ou moins chanceux. Le serveur n'est là que pour parler aux clients les uns aux autres pour qu'ils en sachent suffisamment sur la manière de se connecter à eux. Ensuite, quand leur connexion est établie, le serveur n'est plus impliqué.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2016
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup pour les différentes réponses, j'ai travaillé sur différentes solutions et j'ai réussi à avancer sur certains points.

    Mon serveur écoute sur 2 ports distants, car j'aurais 2 types différents de clients.

    Nom : WhatsApp Image 2016-11-17 at 15.23.36 - copie 2.jpg
Affichages : 1365
Taille : 16,1 Ko

    Lorsqu'un client se connecte, j'affiche ces informations de connexion : IP, port dans lequel il s'est connecté et son port de connexion, ainsi que le nom du client avec qu'il souhaite communiquer :

    Nom : Sans titre - copie.jpg
Affichages : 1320
Taille : 29,8 Ko

    Il ne me reste plus qu'à faire en sorte que la Machine A puise envoyer des message à la Machine G et inversement.
    Savez-vous quel sont les méthodes à utiliser pour réaliser ces opérations ?

  5. #5
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    Sans le fameux punch hole, les clients ne se parlent pas directement: c'est le serveur qui relaie les message.

    Donc, A envoie un message au serveur S. S sait que le destinataire est B. S renvoie donc le message à B.

    Le serveur maintient donc une liste des clients, sait qui est autorisé à communiquer avec qui, et peut router les messages correctement.

    Côté code, une fois que tu as les In/OutputStream issus des Sockets (côté client ou côté serveur), il suffit d'écrire les données voulues dedans (sous forme de byte[]). Le serveur a un peu plus de travail, car il doit maintenir le mapping des communications (savoir que quand on reçoit des données sur la Socket A, il faut renvoyer à la Socket B).

    Après, la façon exacte dont les clients prennent connaissance des destinataires possibles, choisissent quoi envoyer à qui, c'est à toi de l'implémenter. TCP/IP (les Sockets...) nous dit seulement comment transférer des données sur un réseau de façon sûre. Pas comment ordonnancer les communications pour atteindre un objectif.

    Attention à la synchronisation côté serveur, c'est souvent fortement multi-threadé, donc si tu ne gères pas tes verrous correctement, tu peux avoir plein de trucs marrants...
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  6. #6
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Euh, le hole punching n'a rien à voir avec ça, c'est une technique pour tenter d'aider les clients à se connecter directement les uns aux autres, par des moyens plus ou moins chanceux. Le serveur n'est là que pour parler aux clients les uns aux autres pour qu'ils en sachent suffisamment sur la manière de se connecter à eux. Ensuite, quand leur connexion est établie, le serveur n'est plus impliqué.
    Effectivement, j'ai confondu, la technique que j'ai decrit n'est pas du hole punching
    Mais bon, sur le fond, c'est bien ce que je pense que veut faire MrPouletCurry (rediriger les InputStream/OutputStream des clients via le serveur, pas le hole punching).

  7. #7
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2016
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Bonjour,
    Après de nombreux essais j'ai réussi à faire quelque chose de fonctionnelle.
    Donc mon client A peut bien communiquer avec mon client B et inversement à l'aide du serveur S.
    Je laisse le code réalisé, si jamais ça peut intéressé quelqu'un.

    Pour simuler les clients j'ai utilisé le terminal d'OS X. Mais avec des logiciels tel que Hercules SETUP utility (sous windows) ça fonctionne aussi très bien.

    Merci pour les différentes réponses.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    public class Server {
     
        public static void main(String[] zero) {	
            ServerSocket socketServer;        
            Socket clientA = null, clientB = null;        
            InetAddress serverAddress;
     
            try {
                //Création d'une nouvelle socket serveur
                socketServer = new ServerSocket(4002);
                System.out.println("Le serveur écoute sur le port " + socketServer.getLocalPort());
                //Récupération de l'adresse IP du serveur
                serverAddress = InetAddress.getLocalHost();
                //Indique à l'écran l'adresse du serveur
                System.out.println("L'adresse du serveur est " + serverAddress);
     
                //Attend les demandes de connexions de clients
                Thread relationThread = null;
     
                while(true){
                    //Le 1er client connecté sera le Client A
                    if(clientA == null){
                        clientA = socketServer.accept();
                        System.out.println("Client A est connecté et se trouve sur le port " + clientA.getPort());
                    }
                    //Le 2ème client connecté sera le Client B
                    if(clientB == null){
                        clientB = socketServer.accept();
                        System.out.println("Client B est connecté et se trouve sur le port " + clientB.getPort());
                    }
                    //Si les 2 clients sont connectés
                    if(clientA.isConnected() & clientB.isConnected()){
                        //Ils peuvent créer une relation si celle-ci n'existe pas
                        if(relationThread == null){
                            relationThread = new Thread(new Relation(socketServer, clientA, clientB));
                            relationThread.start();
                            System.out.println("La relation entre A et B est établie");
                        }
                    }
                }            
            }catch (UnknownHostException e){ e.printStackTrace();
            }catch (IOException e) { e.printStackTrace(); }
        }
    }
     
    class Relation implements Runnable{
        private Socket clientA, clientB;
        private ServerSocket serverSocket;
        private Thread clientAtoB, clientBtoA;
     
        public Relation(ServerSocket serverSocket, Socket clientA, Socket clientB) {
            this.serverSocket = serverSocket;
            this.clientA = clientA;
            this.clientB = clientB;
        }
     
        @Override
        public void run() {
            try {                
                //Init thread communication A to B
                clientAtoB = new Thread(new RelationInputStream(serverSocket, clientA, clientB));
                //Init thread communication B to A
                clientBtoA = new Thread(new RelationInputStream(serverSocket, clientB, clientA));
                //Start threads
                clientAtoB.start();
                clientBtoA.start();                
            } catch (Exception e) { e.printStackTrace(); }
        }
    }
     
    class RelationInputStream implements Runnable{
        private ServerSocket serverSocket;
        private Socket clientFrom, clientTo;
        private BufferedReader reader;
        private PrintWriter write;
     
        public RelationInputStream(ServerSocket serverSocket, Socket clientFrom, Socket clientTo) {
            this.serverSocket = serverSocket;
            this.clientFrom = clientFrom;
            this.clientTo = clientTo;
        }
     
        @Override
        public void run() {
            String message;
            try {
                reader = new BufferedReader(new InputStreamReader(this.clientFrom.getInputStream()));
                while(true){
                    message = reader.readLine();
                    write = new PrintWriter(clientTo.getOutputStream());
                    write.println(message);
                    write.flush();
                }
            } catch (IOException e) { e.printStackTrace(); }
        }
    }

  8. #8
    Membre à l'essai
    Femme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Autre

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2014
    Messages : 14
    Points : 14
    Points
    14
    Par défaut
    Merci beaucoup Monsieur pour ton aide, c gentil de ta part, j'éspère que ça marche

  9. #9
    Membre à l'essai
    Femme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Autre

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2014
    Messages : 14
    Points : 14
    Points
    14
    Par défaut
    Bonjour Monsieur, malheureusement je n'arrive pas à connecter deux machines, et votre code ne contient pas une classe client. Tu prends le client de type socket, je n'ai pas compris sincèrement :'( Pouvez-vous s'il vous plaît me réexpliquer votre code, Merci d'avance

Discussions similaires

  1. Socket et thread
    Par mayu5 dans le forum Réseau
    Réponses: 6
    Dernier message: 13/05/2008, 00h56
  2. problème socket et thread
    Par dc.sara dans le forum C
    Réponses: 2
    Dernier message: 12/03/2008, 07h58
  3. Programmation réseau : socket et thread
    Par roms712 dans le forum POSIX
    Réponses: 12
    Dernier message: 12/01/2007, 17h27
  4. Sockets TCP/ Threads
    Par guillaume16 dans le forum C++
    Réponses: 3
    Dernier message: 27/07/2006, 23h45
  5. Sockets et threads...
    Par Kiff dans le forum Réseau/Web
    Réponses: 6
    Dernier message: 27/07/2004, 17h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo