C# [Résolu] La classe BinaryReader

A

Anonymous

Invité
#1
Bonjour,

En commençant à travailler un peu sur les sockets, je m'rends compte que c'est vraiment pas pratique de travailler directement sur les octets reçus par le socket.
Pour pallier à ça j'aimerais utiliser la classe BinaryReader (qui elle même demande une classe stream).

J'ai fait ce petit bout de code pour m'entraîner mais rien n'y fait... y'a un détail que je dois pas saisir dans les streams...

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using System.Net.Sockets;
using System.Threading;

namespace MouchBotConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Bienvenue dans les essais de sockets !");
            Console.WriteLine("--------------------------------------");

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Connect("213.248.126.180", 5555);

            if (socket.Connected)
            {
                Console.WriteLine("Connexion au serveur Dofus réussie...");
                Console.WriteLine("");

                NetworkStream stream = new NetworkStream(socket);
                BinaryReader reader = new BinaryReader(stream);

                byte[] response = new byte[1024];
                int bytesRec;

                while (true)
                {
                    bytesRec = socket.Receive(response);
                    Console.WriteLine("{0} octets reçus.", bytesRec);
                    //Console.WriteLine(reader.ReadInt16());

                    for (int i = 0 ; i<bytesRec ; i++)
                    {
                        Console.Write(response[i].ToString("X2") + " ");
                    }
                    Console.WriteLine("");
                    Console.WriteLine("");
                }
            }
            else Console.WriteLine("La connexion au serveur a échoué.");
        }
    }
}
Quelle est la bonne méthode pour utiliser un Networkstream ?

Ou alors
Est-ce que la meilleur solution ne serait pas finalement d'utiliser MemoryStream de response à chaque tour de mon while ?
Faut-il à ce moment là faire un new MemoryStream à chaque fois, ne peut-on pas utiliser le précédent en le resettant ? Je n'ai pas vu de telles fonctions dans MSDN...

D'une manière générale, créer autant d'objets MemoryStream et BinaryReader que j'aurai de réponses risque de générer des problèmes de mémoire non ?? ou est-ce que le C# est assez malin pour détruire les anciens ?





J'ai essayé la seconde méthode mais elle me renvoie un résultat inattendu...

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using System.Net.Sockets;
using System.Threading;

namespace MouchBotConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Bienvenue dans les essais de sockets !");
            Console.WriteLine("--------------------------------------");

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Connect("213.248.126.180", 5555);

            if (socket.Connected)
            {
                Console.WriteLine("Connexion au serveur Dofus réussie...");
                Console.WriteLine("");

                byte[] response = new byte[1024];
                int bytesRec;

                while (true)
                {
                    bytesRec = socket.Receive(response);
                    Console.WriteLine("{0} octets reçus.", bytesRec);
                    
                    MemoryStream stream = new MemoryStream(response);
                    BinaryReader reader = new BinaryReader(stream);
                    Console.WriteLine(reader.ReadInt16());

                    for (int i = 0 ; i<(int)bytesRec ; i++)
                    {
                        Console.Write(response[i].ToString("X2") + " ");
                    }
                    Console.WriteLine("");
                    Console.WriteLine("");
                }
            }
            else Console.WriteLine("La connexion au serveur a échoué.");
        }
    }
}

Voilà le résultat en console :



Ce résultat vous parait normal ? Qu'est ce qui foire alors ?
N'hésitez pas non plus à me faire qq retours sur ma manière d'implémenter, je découvre tout juste le framework .NET :)


Merci et bonne journée !
 
A

Anonymous

Invité
#2
Re: NetworkStream ou MemoryStream ?

Hmmm je viens de découvrir qq chose d'intéressant presque par hasard :)

Je travaillais avec des opérateurs bit à bit pour pallier à mon soucis actuel et au final je me suis rendu compte que pour mon premier packet reçu :

00 05 en binaire 0000 0000 0000 00101
En décalant tout ça de 8 vers la gauche on trouve en binaire 0000 00101 0000 0000 ce qui est égal à 1280 en base 10 !

Le même 1280 que l'on peut lire sur mon screen :D
Le phénomène se repète même pour le deuxième paquet.

Je retourne alors lire le tuto de bouh2 (viewtopic.php?f=41&t=218) et surprise : la classe BinaryReader utilise effectivement un petit endian !

J'ai donc override la méthode BinaryReader avec une classe fille que j'ai implémentée (puisque le C# ne dispose pas de BinaryReaderBigEndian...) :
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MouchBotConsole
{
    class BinaryReaderBigEndian : BinaryReader
    {
        public BinaryReaderBigEndian(Stream stream) : base(stream) { }

        public override short ReadInt16()
        {
            byte[] bytes = base.ReadBytes(2);
            return (short)(bytes[1] | (bytes[0] << 8));
        }
    }
}
Et ça marche :]



PS : Je mets tous ces détails pour des futurs apprentis qui bloqueront comme moi !


Edit : Il n'empeche que ça m'intrigue toujours ces histoires de déclarer des objets en boucle comme ça... avec le même nom.
J'ai fait pas mal de C avant et je dois dire que ça change bien :p
Bon c'est pas aussi dégueulasse que du PHP mais ça l'est assez pour m'intriguer... Je regarderai ça demain si j'ai le temps !
D'ici là n'hésitez pas à me mettre sur la voie :mrgreen:


Edit Edit : Au final, il y a une dll MiscUtil (http://www.yoda.arachsys.com/csharp/miscutil/) bien pratique pour faire du Reader en Big Endian sans avoir à tout recoder.
 
Haut Bas