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

Framework .NET Discussion :

Socket asynchrone et transmission d'objet sérialisé


Sujet :

Framework .NET

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 201
    Points : 196
    Points
    196
    Par défaut Socket asynchrone et transmission d'objet sérialisé
    Bonjour à tous,

    J'ai quelques questions le fonctionnement des Sockets en C#, notemment en mode Asynchrone. Ces même Sockets devant faire transiter des objets sérialisé...

    Mon application fonctionne sur un mode n Clients se connectant à un Serveur.
    Les clients envoient des commandes aux serveurs (sous forme d'objet sérialisé). Le serveurs se chargent de traiter les commandes, et si besoin re dispatch à n Clients des commandes.

    Concrètement, on peu imaginer une chat: Client1 envoi un message au serveur, le serveur le renvoi à tous les Clients. Client1 envoi un message privé, le serveur renvoi au destinataire. Client1 change de pseudo, le serveur effectue le changement, et envoi une commande de mise à jour à tous les autres clients.

    Actuellement, cela fonctionne presque...
    J'ai énormément de mal à faire fonctionner correctement mes Sockets. Les commande sont sérialisé en Byte[], en envoyé de façon classique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnSend, null);//Envoie asynchrone
    [...]
    _socket.EndSend(result);//Envoie terminé
    La réception est semblable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnReceive, null);//En attente de réception
    [...]
    int read = _socket.EndReceive(result);//données reçues
    Le premier problème est sur la taille des commandes envoyées...
    Si mon Byte[] _buffer est de 256 bytes, mais que j'envoi une commande de 512, la réception se fait en "morceaux", voila ma méthode:
    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
    int read = _socket.EndReceive(result);
     
    _logger.DebugFormat("\t{0} bytes receive.", read);
     
    if (_socket.Available > 0)
    {
    	_logger.DebugFormat("\t{0} bytes still available.", _socket.Available);
    	//Il reste de données à lire
     
    	//Lecture des données restantes
    	Byte[] readBuffer = new Byte[_socket.Available];
    	_socket.Receive(readBuffer, 0, readBuffer.Length, SocketFlags.None);
     
    	//Ajout des données supplémentaire au données déjà lues.
    	Array.Resize(ref _buffer, read + readBuffer.Length);
    	readBuffer.CopyTo(_buffer, read);
    }
    Cela fonctionne très bien. Il arrive cependant que plusieurs commandes soit envoyées sur Socket et de façon très rapproché dans le temps, et ma méthode de lecture provoque la concaténation de deux commandes dans mon Byte[] _buffer...
    Et à la dé-sérialisation, seul la première commande est interprété...

    Et là je suis complètement perdu... Je ne sais pas absolument pas comment limiter la lecture d'une commande a la fois, ces commandes étant totalement variable en taille (de 256 bytes, à 2048 pour le moment, mais elle vont évoluer encore...)

    Si quelqu'un à une quelconque idée, ou simple piste je suis preneur !

    Merci de votre aide (et désolé pour le pavé... -_-').

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 201
    Points : 196
    Points
    196
    Par défaut
    Je m'auto-répond

    J'ai finit par m'en sortir donc. J'ai créer un objet de type "Header", que j'envoi en entête de chaque objet devant transiter sur les sockets. Ce header contient tout simplement la taille du buffer de l'objet qui transite.

    Conjointement à cela, j'ai ajouter un lock sur le Send, des sockets clients, qui ne sont donc plus asynchrone. Seule la réception et maintenant asynchrone (ce qui me suffit en fait).
    Le send envoi donc maintenant quoi qu'il arrive mon header (qui ne varie jamais en dimension : Byte[256]) et mon objet. Et même si plusieurs packet se suivent avant d'avoir finit de recevoir. Je sais séparer (via la taille) mes différents objets et entête...

    Je laisse un bout de code, qui sera surement plus parlant que mon explication tordu
    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
    private void OnReceive(IAsyncResult result)
    {
    	try
    	{
    		_logger.Info("Receiving data");
     
    		_socket.EndReceive(result);
    		_readBuffer.AddRange(_buffer);
    		int read = _readBuffer.Count;
     
    		while (read < SocketPacket.HeaderSize)
    		{
    			read+=_socket.Receive(_buffer, 0, _buffer.Length, SocketFlags.None);
    			_readBuffer.AddRange(_buffer);
    		}
     
    		Byte[] headerBuffer = new Byte[SocketPacket.HeaderSize];
    		_readBuffer.CopyTo(0, headerBuffer, 0, headerBuffer.Length);
    		_readBuffer.RemoveRange(0, headerBuffer.Length);
     
    		SocketPacket.SocketPacketHeader header = SerializerHelper.Deserialize(headerBuffer.ToArray());
     
    		read = _readBuffer.Count;
     
    		while (read < header.BufferSize)
    		{
    			read+=_socket.Receive(_buffer, 0, _buffer.Length, SocketFlags.None);
    			_readBuffer.AddRange(_buffer);
    		}
     
    		Byte[] contentBuffer = new Byte[header.BufferSize];
    		_readBuffer.CopyTo(0, contentBuffer, 0, contentBuffer.Length);
    		_readBuffer.RemoveRange(0, contentBuffer.Length);
     
    		RaiseEvent(OnDataReceived, new SocketDataEventArgs(contentBuffer));
     
    		_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnReceive, null);
    	} catch (SocketException exception)
    	{
    		RaiseEvent(OnDisconnected, EventArgs.Empty);
    		_logger.Error(exception.Message, exception);
    	}
    }
     
    public void Send(object obj)
    {
    	_logger.Info("Sending data");
    	SocketPacket packet = new SocketPacket(obj);
    	lock (writeLock)
    	{
    		Byte[] headerBuffer = SerializerHelper.Serialize(packet.GetHeader());
    		_socket.Send(headerBuffer, 0, headerBuffer.Length, SocketFlags.None);
    		_socket.Send(packet.Buffer, 0, packet.Buffer.Length, SocketFlags.None);
    	}
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WinAPI][winsock2][visual C++]socket asynchrone
    Par jldgbu dans le forum Windows
    Réponses: 2
    Dernier message: 15/10/2006, 18h34
  2. UDP/TCP multithreading/sockets asynchrones
    Par narkotik dans le forum C++
    Réponses: 4
    Dernier message: 25/07/2006, 11h35
  3. Erreur Socket Asynchrone 10053
    Par QAYS dans le forum Delphi
    Réponses: 2
    Dernier message: 16/06/2006, 07h44
  4. [Sécurité] Problème de récupération d'objet sérialisé
    Par Mysticlolly dans le forum Langage
    Réponses: 6
    Dernier message: 31/03/2006, 14h16
  5. connexion socket asynchrone
    Par jagboys dans le forum C++Builder
    Réponses: 3
    Dernier message: 17/06/2005, 17h04

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