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

C# Discussion :

[Socket] Etape du client?


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut [Socket] Etape du client?
    Bonjour,

    je suis en train de développer le client d'une application destinée à se connecter à un serveur distant.

    J'ai regardé vite fait le code de Putty, et j'ai vu qu'il faisait un select() (de socket), ce n'est pas réservés au serveur?

    Pour ma part, j'aimerai savoir quand des données arrivent dans le flux et les afficher en temps réel, comment puis-je faire cela?

    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    Bonjour,

    la fonction select à pour but de savoir s'il est possible de lire ou d'écrire sur des fd. Elle n'est en aucun cas réservée à une utilisation serveur.
    En C, select serait une bonne méthode (bien qu'il mette en attente le programme).
    En C#, tu devrais regarder du coté des méthodes asynchrones (comme BeginReceive).

  3. #3
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    Bonjour,

    je veux faire de la lecture synchrone (vu que je souhaite réaliser une console), avez-vous des exemples d'utilisations de select du côté client?

    Le select implique qu'on fasse un listen non?

    Bref, un petit topo complet sur l'utilisation du select() serait plutôt pas mal

    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    Bonjour,

    Si on parle bien de C#, tu possèdes 2 méthodes pour vérifier des sockets :
    - Socket.Select (static) pour vérifier plusieurs sockets en même temps
    - Sockets.Poll pour faire la même vérification mais sur une seul Socket.

    Pour des cas d'utilisation, je t'invite à suivre les liens, les exemples sont assez parlant pour moi.

  5. #5
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    je vais tester ça se soir

    Je pense une socket en synchrone pour le frontend (interface utilisateur) et une autre en asynchrone pour des traitements de fond que l'utilisateur n'a pas besoin de voir


    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  6. #6
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    Bonsoir,

    j'ai 2 problèmes majeurs :
    1 - je dois faire une lecture clavier sur l'entrée standard, mais ne pas l'afficher dans la console, car seul les caractères renvoyés par l'hôte distant sont à afficher.
    Exemple : je tape mon mot de passe, je vois la trame passer du client vers le serveur, mais ne me répond pas (normal, la saisie du mot de passe est invisible).

    Comment faire cela?

    2- J'ai mon serveur qui m'affiche les données avec une itération de retard ()
    Exemple : je vois que le serveur m'envoie la trame "Password :" vers mon client, seulement cette dernière ne s'affiche pas dans l'écran, il faut que je saisisse mon mot de passe et ensuite seulement je la vois ()

    Voici mon code :

    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
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    using System;
    using System.Net.Sockets;
    using System.Text;
    using System.Net;
     
    namespace TestRLogin
    {
        class Program
        {
            public static void write(Socket s, char c)
            {
                char[] toSend = { c };
                if (s.Send(new UTF8Encoding().GetBytes(toSend)) <= 0)
                {
                    Console.Error.WriteLine("Echec de l'envoi");
                }
            }
     
            public static string read(Socket s)
            {
                int size, count;
                byte[] toread;
                string text = String.Empty;
     
                while (s.Available > 0)
                {
                    size = s.Available;
                    toread = new byte[size];
                    count = s.Receive(toread, size, SocketFlags.None);
     
                    text += new UTF8Encoding().GetString(toread);
                    Console.WriteLine("-> {0} octets lus sur {1} octets disponibles", count, size);
                }
                return text;
            }
            public static byte[] resize(int width, int height)
            {
     
                byte[] b = { 0xFF, 0xFF, 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
     
                b[6] = (byte) (width >> 8);
                b[7] = (byte) (width & 0xFF);
                b[4] = (byte) (height >> 8);
                b[5] = (byte) (height & 0xFF);
                return b;
            }
     
            static void Main(string[] args)
            {
                try
                {
                    byte[] data = new ASCIIEncoding().GetBytes(" user user xterm/38400 ");
     
                    for (int i = 0; i < data.Length; i++)
                    {
                        if (data[i] == 32)
                            data[i] = 0x00;
                    }
     
                    IPEndPoint host = new IPEndPoint(Dns.GetHostEntry("hostname").AddressList[0], 513);
                    IPEndPoint local = new IPEndPoint(IPAddress.Any, 1021);
     
                    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    s.Bind(local);
                    s.DontFragment = true;
                    s.NoDelay = true;
                    s.Connect(host);
     
                    // Connexion
                    int count = s.Send(data);
                    Console.WriteLine("{0} octets envoyés", count);
     
                    count = s.Send(resize(80, 24));
                    s.Send(new byte[] {0x00});
                    Console.WriteLine("{0} octets envoyés", count);
     
                    while (true)
                    {
                        if (s.Poll(200, SelectMode.SelectRead))
                        {
                            Console.Write(read(s));
                        }
                        else if (s.Poll(200, SelectMode.SelectWrite))
                        {
                            write(s, (char)Console.Read());
                        }
                        else
                        {
                            break;
                        }
                    }
     
                    s.Shutdown(SocketShutdown.Both);
                    s.Close();
                    Console.WriteLine("Connexion fermée");
     
                }
                catch (SocketException se)
                {
                    Console.WriteLine(se.Message);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
                Console.Read();
            }
        }
    }
    Aurais-je coder une horreur quelque part?
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    Bonjour,

    Je me demande si ce ne serais pas le même problème qu'avec printf en C, soit que la méthode n'écrit sur la sotrie standard que quand elle a suffisement de caractère ou qu'elle a un \n.
    Essaye de rajouter un flush après tes appel à write qui doivent s'afficher immédiatement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Console.Out.Flush();

  8. #8
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    Merci pour le Console.Flush() ! C'est bien ça


    Cette histoire de Poll et Select me prend vraiment la tête, du coup j'ai fini par laisser de côté et passer par des threads, un pour la lecture, l'autre pour l'écriture. Du coup, plus de soucis.

    Par contre, j'aimerai savoir comment faire pour envoyer caractère par caractère au serveur, mais je n'ai pas trouvé , a noté qu'il n'y pas de méthode Flush sur les sockets

    J'ai tenté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, 1);
    Mais ça n'a rien changé, des idées?
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    Bonsoir,

    Essaye de mettre l'option de Socket NoDelay à true.
    ça empeche le framework d'utiliser un algorithme pour limiter le nombre de transfert sur le réseau en collant plusieurs message dans une même trame.

  10. #10
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    C'est dans le code précédent, c'est déjà à true
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    En effet, je ne l'avais pas vu.

    Sinon, je pense que le problème ne vient pas de la socket, mais de la méthode utilisé pour récupérer les touches utilisés sur le clavier.
    En effet, même si Read ne retourne les valeurs que caractère par caractère, il reste bloquant tant que la touche entré n'est pas appuyée.
    Une solution serait d'utiliser ReadKey à la place, mais il faut aussi gérer les touches qui ne produisent pas de caractère ou pas de caractère imprimable.

  12. #12
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Par défaut
    J'avais eu cette même idée hier soir et c'est vrai que ça fonctionne beaucoup mieux !

    Le code :

    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
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    using System;
    using System.Net.Sockets;
    using System.Text;
    using System.Net;
    using System.Threading;
    using System.IO;
     
    namespace TestRLogin
    {
        public class Program
        {
            public static void write(object o)
            {
                TcpClient tcp = new TcpClient();
                tcp.Client = (Socket)o;
                StreamWriter stream = new StreamWriter(tcp.GetStream(), Encoding.UTF8);
                stream.AutoFlush = true;
     
                ConsoleKeyInfo toSend;
                while (true)
                {
                    toSend = new ConsoleKeyInfo();
                    toSend = Console.ReadKey(true);
     
                    try
                    {
                        stream.Write(toSend.KeyChar);
                    }
                    catch (Exception) { }
     
                    Thread.Sleep(100);
                }
            }
     
            public static void read(object o)
            {
                TcpClient tcp = new TcpClient();
                tcp.Client = (Socket)o;
                NetworkStream stream = tcp.GetStream();
                UTF8Encoding encoder = new UTF8Encoding();
                int c;
     
                while (true)
                {
                    while (stream.DataAvailable)
                    {
                        c = stream.ReadByte();
     
                        if (c == 0x00)
                        {
                            Console.WriteLine("[BACK]");
                        }
                        if (c == 0x80)
                        {
                            stream.Write(resize(80, 24), 0, 12);
                        }
                        Console.Write(encoder.GetString(new byte[] { (byte)c }));
                        Console.Out.Flush();
                    }
                    Thread.Sleep(100);
                }
            }
     
            public static byte[] resize(int width, int height)
            {
     
                byte[] b = { 0xFF, 0xFF, 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
     
                b[6] = (byte) (width >> 8);
                b[7] = (byte) (width & 0xFF);
                b[4] = (byte) (height >> 8);
                b[5] = (byte) (height & 0xFF);
                return b;
            }
     
            static void Main(string[] args)
            {
                try
                {
                    byte[] data = new ASCIIEncoding().GetBytes(" user user xterm/9600 ");
     
                    for (int i = 0; i < data.Length; i++)
                    {
                        if (data[i] == 32)
                            data[i] = 0x00;
                    }
                    IPEndPoint host = new IPEndPoint(Dns.GetHostEntry("server").AddressList[0], 513);
                    IPEndPoint local = new IPEndPoint(IPAddress.Any, 1021);
     
                    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    s.Bind(local);
                    s.DontFragment = true;
                    s.NoDelay = true;
                    s.Connect(host);
     
                    // Connexion
                    int count = s.Send(data);
     
                    Thread reader = new Thread(Program.read);
                    reader.Start(s);
     
                    Thread writer = new Thread(Program.write);
                    writer.Start(s);
     
                    while (true)
                    {
                        Thread.Sleep(100);
                    }
     
                    s.Shutdown(SocketShutdown.Both);
                    s.Close();
                    Console.WriteLine("Connexion fermée");
     
                }
                catch (SocketException se)
                {
                    Console.WriteLine(se.Message);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
                Console.Read();
            }
        }
    }


    J'ai un autre souci, le serveur me renvoie les données en double dans les trames, je pense que c'est du a un écho, mais je ne sais pas comment l'enlever

    Voici par exemple une trame que je reçois :
    \033]0;user@server: ~\auser@server:~$
    Au lieu de :
    user@server:~$
    P.S : pour la méthode, je passe par un StreamWriter pour envoyer mes données sur le réseau et tout se passe bien , mais pour la méthode Read, si je passe par un StreamReader, je ne récupère rien. Etrange

    Une option permet-elle de pallier à cela?
    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

Discussions similaires

  1. Socket envoi message Client/Serveur
    Par sebkill dans le forum C#
    Réponses: 27
    Dernier message: 28/05/2008, 22h34
  2. Problème communication sockets serveur mutli-client
    Par muad'dib dans le forum Réseau
    Réponses: 5
    Dernier message: 17/05/2007, 02h21
  3. socket application coté client ?
    Par storm_3000 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 28/08/2006, 14h13
  4. Socket serveur et client
    Par StreamEarth dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 21/08/2006, 16h00
  5. [Socket] Plusieurs socket pour un client
    Par meda dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 24/05/2005, 17h24

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