none
[Socket] Reception incomplète de taille inconnue RRS feed

  • Question

  • Bonjour à tous,

    Amis des sockets et de la programmation réseaux, ce post s'adresse à vous !

    Je dois réaliser un client qui se connecte à un serveur pour y récupérer des images (pour ensuite les afficher ou les enregistrer, mais là n'est pas la question...).
    Je précise d'entrée que je n'ai pas accès au sources du serveur, et que par conséquent, je ne peux que me plier aux exigences du protocole mis en place.

    La communication se base sur les échanges suivants :

    1. Mon client se connecte au serveur en TCP et ouvre une connexion que nous appellerons la connexion de contrôle
    2. Il ouvre ensuite une connexion TCP sur laquelle il se met en écoute, nous l'appellerons la connexion de données
    3. Il envoie au serveur des informations sur la connexion de données (notamment le port sur lequel il est en écoute)
    4. Le serveur se connecte sur la connexion de données


    Ensuite le client demande des images via la connexion de contrôle, et le serveur les lui envoie via la connexion de données.

    J'ai entrepris de réaliser ce projet en C#. Mais voilà je me heurte à un problème :
    Lorsque le serveur envoie les données de l'image, je n'en reçois pas la totalité. Et cela me semble étrange, car j'utilise les fonctions de connexion synchrones qui sont censées être bloquantes.

    Voilà comment sont construits mes 2 sockets data et ctrl :



    Socket data = null, ctrl = null;
    
    Socket dataInit = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    dataInit.Bind(new IPEndPoint(IPAddress.Parse(server), portData));
    dataInit.Listen(1);
    
    ctrl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    ctrl.Connect(new IPEndPoint(IPAddress.Parse(server), portCtrl));
    string Get = "informations sur la connexion de données...";
    Byte[] ByteGet = ASCII.GetBytes(Get);
    ctrl.Send(ByteGet, ByteGet.Length, 0);
                   
    data = dataInit.Accept();
    Puis, pour recevoir les données j'appelle la méthode Receive sur la socket data .

    Le problème est qu'apparemment toutes les données n'ont pas eu le temps d'arriver car je récupère seulement les X premiers octets. Mais si je "fais une pause" avant d'appeler la méthode Receive (par exemple en rajoutant une messagebox qui attend mon clic), alors cette fois je récupère bien toute les informations correctement.

    J'ai essayé d'utiliser un NetworkStream, mais j'ai alors le même problème avec la méthode Read, et j'ai également essayé de boucler sur l'appel à Receive, mais là mon programme se bloque après quelques appels à Receive (appel bloquant cette fois ci ?)

    Je ne sais pas du tout comment régler mon problème :/
    En fait cela serait surement plus simple si je connaissais avec précision la taille des données à recevoir, qui varient en fonction de la taille de l'image (qui n'est jamais la même)

     

    Un grand merci d'avance à tous ceux qui pourront m'aider :)

    ++
    NiklosKoda

    jeudi 25 mars 2010 07:48

Toutes les réponses

  • Bonjour,

     

    Quelle version de la fonction Receive avez-vous utilise ?

     

    Si vous mettez un point d’arrêt après appeler Connect et avant Receive, vous recevrez tout le fichier ? Essayez d’utiliser la methode Poll  pour vérifier si la connexion a été établie avant d’utiliser Receive.

     

    Cordialement,

    Alex


    Alex Petrescu - MSFT
    vendredi 26 mars 2010 14:40
  • Bonjour,

     

    J'utilise cette version de Receive : Socket:: Receive(Byte[] , Int32, Int32, SocketFlags)

     

    La méthode Poll, elle renvoie bien true (je l'appelle de cette manière : data.Poll(100, SelectMode.SelectRead)).

     

    Et en ce qui concerne la méthode Connect, j'obtiens l'exception : "a connect request was made on an already connected socket IP:PORT" si je l'appelle ...

     

    Merci de votre première réponse.

    Pour le moment j'ai contourné le problème en mettant un timeout au socket, comme ceci :

    data.ReceiveTimeout = 100;
    try{
        while(1)
        {
            data.Receive(buff);
            [add buff qq part];
        }
    }
    catch(SocketException se) {}
    

    Cette solution ne me satisfait qu'à moitié...donc si quelqu'un en a une autre je lui serais grandement reconnaissant.

    Merci d'avance.

    Niklos

    • Marqué comme réponse Alex Petrescu lundi 29 mars 2010 09:55
    • Marqué comme réponse Alex Petrescu lundi 29 mars 2010 09:55
    • Non marqué comme réponse NiklosKoda mercredi 21 avril 2010 10:39
    dimanche 28 mars 2010 08:37
  • Bonjour,

     

    Je n’ai pas compris l’exception que vous recevrez avec la méthode Connect. Vous recevrez cette exception la première fois que vous appelez Connect, ou si vous appelez Connect deux fois pour le même objet Socket ?

     

    Cordialement,

    Alex


    Alex Petrescu - MSFT
    lundi 29 mars 2010 09:57
  • Bonjour,

     

    En fait pour la socket "data" je n'appelle pas Connect, mais Accept, comme ceci :

    Socket dataInit = new
     Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    dataInit.Bind(new IPEndPoint(IPAddress.Parse(server), portData));
    dataInit.Listen(1); data = dataInit.Accept();

     

    Donc je ne peux pas appeler Accept pour cette socket, d'où l'exception obtenue.

    lundi 29 mars 2010 12:11