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 :

TCP read tant qu'on recoit des choses


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 037
    Par défaut TCP read tant qu'on recoit des choses
    Bonjour

    J'ai besoin de recevoir des données en tcp dont je ne connais pas la taille exacte et pour laquelle je n'ai pas de marqueur de fin genre le "EOF" utilisé dans les exemples du MSDN

    J'ai fait cette méthode, copieusement pompée sur des exemples.
    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
                static void ProcessClient(TcpClient client, X509Certificate certificate)
                {
                    // A client has connected. Create the SslStream using the client's network stream.
                    var sslStream = new SslStream(client.GetStream(), false);
     
     
                    try
                    {
     
                        // Authenticate the server and NOT requires the client to authenticate.
                        sslStream.AuthenticateAsServer(certificate, false, SslProtocols.Tls, true);
     
                        // Authenticate the server and requires the client to authenticate.
    //sslStream.AuthenticateAsServer(certificate, true, SslProtocols.Default, true);
     
     
                        // Display the properties and settings for the authenticated stream.
                        DisplaySecurityLevel(sslStream);
                        DisplaySecurityServices(sslStream);
                        DisplayCertificateInformation(sslStream);
                        DisplayStreamProperties(sslStream);
     
                        // Set timeouts for the read and write to 5 seconds.
                        sslStream.ReadTimeout = 250;
                        sslStream.WriteTimeout = 5000;
                        // Read a message from the client.   
     
                        Console.WriteLine("Waiting for client message...");
     
                        byte[] buffer = new byte[20000];
     
                        // attente réponse le temps du timeout
                        int Position = 0; // position dans le buffer = nombre total d'octets recus
                        int bytes = -1;
                        do
                        {
                            bytes = sslStream.Read(buffer, Position, (buffer.Length - Position));
                            Console.WriteLine("recu : {0}o", bytes);
                            Position += (int)bytes;
                        } while (bytes !=0 );
     
     
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Recu texte : {0}", System.Text.Encoding.ASCII.GetString(buffer,0,Position));
                        Console.Write("Recu bytes :");
                        for (int i = 0; i < Position; i++)
                        {
                            Console.Write("{0}-", buffer[i].ToString());
                        }
                        Console.ResetColor();
     
                        // Write a message to the client.
                        byte[] message = Encoding.ASCII.GetBytes("Reponse du serveur de demo !!");
                        Console.WriteLine("\r\nSending hello message.");
                        sslStream.Write(message);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: {0}", e.Message);
                        if (e.InnerException != null)
                        {
                            Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                        }
                        Console.WriteLine("Authentication failed - closing the connection.");
                        sslStream.Close();
                        client.Close();
                        return;
                    }
                    finally
                    {
                        // The client stream will be closed with the sslStream
                        // because we specified this behavior when creating
                        // the sslStream.
                        sslStream.Close();
                        client.Close();
                    }
                }
    Le morceau concerné ici est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int Position = 0; // position dans le buffer = nombre total d'octets reçus
                        int bytes = -1;
                        do
                        {
                            bytes = sslStream.Read(buffer, Position, (buffer.Length - Position));
                            Console.WriteLine("recu : {0}o", bytes);
                            Position += (int)bytes;
                        } while (bytes !=0 );
    Mon gros soucis est que forcément on sort de là en timout et que donc forcément j'ai une exception qui me fait sauter. Je tourne le truc dans tous les sens je ne vois pas comment faire et pourtant j'imagine bien que d'autres que moi ont eu à recevoir des choses en TCP sans en connaitre la taille et sans avoir d'identifiant de fin de message !
    -J'ai imaginé désactiver le timout et le refaire moi même avec un Stopwatch sw = new Stopwatch(); mais je ne peux pas interrompre le read avec un tel timout perso, seul le timout du read le peut
    -J'ai imaginé vérifier dans l'exception si on a déjà reçu des choses mais d'une part je ne trouve pas le nom de l'exception timout (IOexception c'est vague) et d'autre part il est déjà trop tard une fois que l'exception a sautée

    Peut on désactiver une exception spécifique une fois un premier read terminé avec réception d'un nombre de byte >0 ?
    Quelle autre solution ?

    Merci

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    déjà il y a 2 méthodes de lecture sur du socket
    .read et .beginread (sur les nouvelles classes il doit y avoir des tasks, mais je vais partir du principe peu fondé que tu utilises tcplistner et/ou tcpclient)

    .read lit x octet, cette fonction est bloquante jusqu'à réception d'au moins un octet
    elle te retournes le nombre d'octets lus, tout en les placant dans le tableau que tu fournis

    .beginread permet de préciser un callback (= une méthode à appeler quand au moins un octet arrive, donc un peu comme un event)
    elle démarre un thread qui va attendre qu'il y ait des octets dans le buffer, ne bloquant donc pas l'interface ni l'exécution du code
    dans le callback tu pourras faire .endread pour avoir les octets et redemander un .beginread pour lire la suite
    tu peux alors donc lire indéfiniment

    avec .read tu peux aussi lire indéfiniment, mais pour ne pas bloquer l'interface, tu devras toi même démarrer un thread pour avoir le même effet
    dans l'exemple ils mettent un timeout car .Read étant bloquant on ne peut pas rester dans cette boucle sans fin
    l'exemple est donc utilisable pour un envoi avec une fin de prévue et assez rapide
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. Réponses: 13
    Dernier message: 09/11/2006, 23h37
  2. [Socket] savoir s'il reste des chose a lire?
    Par piff62 dans le forum Langage
    Réponses: 4
    Dernier message: 05/10/2006, 17h15
  3. [Conception] afficher des choses en fonction du clic
    Par Henry9 dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 03/10/2006, 15h55
  4. [MySQL] Rentrer des choses dans une base de données garce à un post
    Par BernardT dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 20/03/2006, 21h07
  5. [pratique web] Aspirer un site pour en apprendre des choses?
    Par sempire dans le forum Général Conception Web
    Réponses: 11
    Dernier message: 11/11/2005, 18h07

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