[Resolu (Merci MagicBuzz)] Problème pour lire un flux de byte en C#

Problème pour lire un flux de byte en C# [Resolu (Merci MagicBuzz)] - C#/.NET managed - Programmation

Marsh Posté le 02-04-2003 à 19:25:55    

bonjour,
 
j'ai un problème pour lire des données sur une socket (un flux de byte dont je connais la taille par avance (intSize en paramètre): ca ne lit pas tout, juste une partie.
 
Le programme qui envoie les données marche normalement (i.e. il envoie tout). J'ai essayé plein de trucs différents et aucun ne marche. Le mieux que j'ai trouvé c'est un while avec beginRead, mais meme la il me manque un bout à la fin.
 
Si quelqu'un avait un bout de code fonctionnel, ca m'aiderait bien.
Nota: le flux de données est un flux binaire quelconque (un fichier PDF dans mes tests).
 
D'avance Merci :)
 
Le code problèmatique (il est dans un web service):
 
//Entrée: str : la commande a envoyer sur le serveur pour déclencher l'envoie du fichier
//strHost : l'hôte à appeller (i.e. le serveur)
//intSize : la taille du fichier que l'on va recevoir

Code :
  1. private byte [] RecupereFichier (string str, string strHost, int intSize)
  2. {
  3. //Le conteneur du fichier
  4. byte[] lbytes = new byte[intSize];
  5. try
  6. {
  7.   TcpClient tcpclnt = new TcpClient();
  8.   tcpclnt.Connect(strHost, 20022); //port 20022
  9.   NetworkStream stm = tcpclnt.GetStream(); //j'ai essayé aussi avec Stream tout court
  10.      
  11.   //Envoie la commande str chez le serveur
  12.   ASCIIEncoding asen = new ASCIIEncoding();
  13.   byte[] ba = asen.GetBytes(str);
  14.   stm.Write(ba, 0, ba.Length);
  15.   //Lit le fichier que le serveur envoie: (pbm: ne lit pas tout)
  16.   //J'ai essayé aussi en remplacant (int) tcpclnt.ReceiveBufferSize par intSize
  17.   stm.Read(lbytes, 0, (int) tcpclnt.ReceiveBufferSize);
  18.   //On ferme tout
  19.   stm.close();
  20.   tcpclnt.Close();
  21.   return lbytes;
  22. }
  23. catch (Exception e)
  24. {
  25.   Console.WriteLine(e.StackTrace);
  26. }
  27. return lbytes; //jamais appelé normalement
  28. }


Message édité par ToxicAvenger le 03-04-2003 à 22:37:51
Reply

Marsh Posté le 02-04-2003 à 19:25:55   

Reply

Marsh Posté le 02-04-2003 à 19:57:48    

T'es sûr que "intSize" est plus grand que "tcpclnt.ReceiveBufferSize" ?

Reply

Marsh Posté le 02-04-2003 à 20:06:18    

MagicBuzz a écrit :

T'es sûr que "intSize" est plus grand que "tcpclnt.ReceiveBufferSize" ?


 
affirmatif. En tout cas (testé via l'interface web du webservice), "intSize" contient bien la taille du fichier. Donc en tout état de cause, "tcpclnt.ReceiveBufferSize" est <= a "intSize" (il envoiie que le contenu du fichier, sans balise ou autres fioritures).
 
De plus, je recupere dans une autre fonction le tableau de bytes retourné et j'enregistre ca dans un fichier, dont la taille vaut "intSize". Le début est bien rempli, mais la fin du fichier est rempli de 0 (en hexa).
 
 :cry:

Reply

Marsh Posté le 02-04-2003 à 20:18:26    

OK.
 
Bon, alors ça doit être bêtement que tu dépasses la taille du buffer winsocks (ça doit être dans les 4 Ko je crois)
 
T'as essayé d'envoyer ton fichier en petits morceaux ?

Reply

Marsh Posté le 02-04-2003 à 20:29:57    

mmmm, ouais en fait, j'ai dû dire une connerie, après vérification, il n'a pas l'air d'y avoir de taille maximum de buffer.
 
vais voir si j'arrive à faire un truc qui marche, et si c'est le cas, je te le poste;

Reply

Marsh Posté le 02-04-2003 à 20:31:17    

MagicBuzz a écrit :

OK.
 
Bon, alors ça doit être bêtement que tu dépasses la taille du buffer winsocks (ça doit être dans les 4 Ko je crois)
 
T'as essayé d'envoyer ton fichier en petits morceaux ?


 
ca passe encore par winsock ??? ca date de win95 ca qd meme. Depuis le temps, je pensais qu'ils avaient mis autre chose. 4 ko c'est peu. Pour un fichier pdf de 300 ko, ca en fait des petits morceaux...
 
Surtout que dans l'hyper terminal, je recois bien tout (avec le meme serveur qui envoit le fichier d'un seul bloc, et pas en petit morceau de 4k). Donc, c'est pas logique ca. Comment recevoir 4k par 4k, si on envoie tout d'un coup ? Faudrait envoyer aussi 4k par 4k non ? ce qui n'est pas le cas, puisqu'avec l'hyper terminal ca marche...  :pt1cable:

Reply

Marsh Posté le 02-04-2003 à 20:34:11    

MagicBuzz a écrit :

mmmm, ouais en fait, j'ai dû dire une connerie, après vérification, il n'a pas l'air d'y avoir de taille maximum de buffer.
 
vais voir si j'arrive à faire un truc qui marche, et si c'est le cas, je te le poste;


 
merci, je commence a péter un cable là... surtout que sur la plateforme de développement qu'on impose je n'ai pas acces au debugger (super pour les webservice...))

Reply

Marsh Posté le 02-04-2003 à 21:09:32    

Euh...
 
C pas gagné :D
 
T'ain, ça fait un bout de temps que j'ai pas fait de C#, et J'arrive même pas à lire un fichier :D
 
Y'a quoi qui cloche dans mon code :??:
 

Code :
  1. private void button1_Click(object sender, System.EventArgs e)
  2.  {
  3.   const int BUFFER_SIZE = 1048576; // 1 Mo
  4.   byte[] contenu = new byte[BUFFER_SIZE];
  5.   System.IO.Stream fichier = new System.IO.FileStream(textBox1.Text, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, BUFFER_SIZE, false);
  6.   while (fichier.Position < fichier.Length)
  7.    label1.Text = fichier.Read(contenu, System.Convert.ToInt32(fichier.Position), System.Convert.ToInt32(System.Math.Min(BUFFER_SIZE, fichier.Length - fichier.Position))).ToString() + " / " + fichier.Length.ToString();
  8.  }


 
J'ai cette erreur dès la lecture du premier block de 1 Mo :
Ca plante sur la ligne :
 

Code :
  1. label1.Text = fichier.Read(contenu, System.Convert.ToInt32(fichier.Position), System.Convert.ToInt32(System.Math.Min(BUFFER_SIZE, fichier.Length - fichier.Position))).ToString() + " / " + fichier.Length.ToString();


 

Citation :

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
 
Additional information: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.


 
D'où y'a une merde ? :sweat:
 
Le buffer "contenu" est rempli.
Length < Position
Par moment, le débugguer me met en rouge la moitié des valeurs dans le buffer.
Deplus, là il met en rouge fichier.Position, la valeur du caption, et la taille du tableau du buffer.
J'ai réessayé avec 1024 comme BUFFER_SIZE, mais rien n'y fait.
 
Deplus, il me semble que c'est cette méthode que j'utilisais à l'époque quand j'avais fait un prog qui lisait par block de 5 Mo (ce qui me donnait le meilleur résultat au niveau perfs)
 
 
C vraiment pas gagné, d'ici que j'arrive à faire tourner le winsock... :D


Message édité par MagicBuzz le 02-04-2003 à 21:12:50
Reply

Marsh Posté le 02-04-2003 à 21:17:30    

... quel crétin des Alpes :D
 
Le prochain coup, je lirai les defs des paramètres dans les fonctions :lol:
 
OffSet de "Read" c'est l'offset dans le tableau, pas dans le fichier :D

Reply

Marsh Posté le 02-04-2003 à 21:24:54    

C'est koi tes lignes "Using" ?
 
Je trouve pas TcpClient dans les libs de .NET, et je trouve encore moins le composant que tu utilises si c'est un composant.
 
hey mais je suis bigleux ce soir moi...
 
System.Net.Sockets.TcpClient


Message édité par MagicBuzz le 02-04-2003 à 21:27:18
Reply

Marsh Posté le 02-04-2003 à 21:24:54   

Reply

Marsh Posté le 02-04-2003 à 21:28:34    

MagicBuzz a écrit :

C'est koi tes lignes "Using" ?
 
Je trouve pas TcpClient dans les libs de .NET, et je trouve encore moins le composant que tu utilises si c'est un composant.
 
hey mais je suis bigleux ce soir moi...
 
System.Net.Sockets.TcpClient


 
using System.Text;
using System.Net.Sockets;
 
Edit: grillaid  ;)  
 
Bon, c'est pas gagné non plus pour toi a ce que je vois.
 
Le meilleur truc que j'ai obtenu c'est avec une boucle while (i<intSize) qui lit avec des beginRead. Ca lit bien bloc par bloc, par contre qd je copie le tableau de bytes fraichement lue dans un tableau de byte (celui que je renvoie a la fin) ca copie rien. J'ai tout essayé (.setValue, .CopyTo, une copie avec boucle for() byteResultat[i]=byteLue[i] etc...)
 
 :pt1cable:


Message édité par ToxicAvenger le 02-04-2003 à 21:31:37
Reply

Marsh Posté le 02-04-2003 à 22:34:27    

Bon, c'est sur la bonne voie, j'ai juste un petit problème à la con, et après je poste mon truc, ça a l'air de marcher sans problème.
 
(par contre, c'est codé à la vas-y comme j'te pousse, en monothread et tout :D)

Reply

Marsh Posté le 02-04-2003 à 22:41:52    

Bon, voilà, mon truc marche.
 
PS: je transmet pas la taille du fichier, ce qui fait que le fichier créé est un multiple de "BUFFER_SIZE" de taille immédiatement suppérieure à la taille du fichier.
 
Server :

Code :
  1. private void Form1_Load(object sender, System.EventArgs e)
  2.  {
  3.   const int BUFFER_SIZE = 1048576; // 1 Mo
  4.   byte[] contenu = new byte[BUFFER_SIZE];
  5.   int buff_size;
  6.   System.IO.Stream fichier = new System.IO.FileStream(textBox1.Text, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, BUFFER_SIZE, false);
  7.   System.Net.Sockets.TcpListener tcpServer = new System.Net.Sockets.TcpListener(11000);
  8.   tcpServer.Start();
  9.   try
  10.   {
  11.    //Accept the pending client connection and return a TcpClient initialized for communication.
  12.    System.Net.Sockets.TcpClient tcpClient = tcpServer.AcceptTcpClient();
  13.    System.Net.Sockets.NetworkStream networkStream = tcpClient.GetStream();
  14.    tcpClient.SendBufferSize = BUFFER_SIZE;
  15.    while (fichier.Position < fichier.Length)
  16.    {
  17.     buff_size = System.Convert.ToInt32(System.Math.Min(BUFFER_SIZE, fichier.Length - fichier.Position));
  18.     fichier.Read(contenu, 0, System.Convert.ToInt32(System.Math.Min(BUFFER_SIZE, fichier.Length - fichier.Position)));
  19.     networkStream.Write(contenu, 0, buff_size);
  20.    }
  21. //    string responseString = "You have successfully connected to me";
  22. //    Byte[] sendBytes = responseString;
  23. //    networkStream.Write(sendBytes, 0, sendBytes.Length);
  24. //    label1.Text = "Message Sent /> : " + responseString;
  25.    
  26.    tcpClient.Close();
  27.   }
  28.   catch (System.Exception exp)
  29.   {
  30.    label1.Text = exp.ToString();
  31.   }
  32.   //   System.Net.Sockets.TcpClient Client = new System.Net.Sockets.TcpClient();
  33.   //   Client.Connect("127.0.0.1", 1001);
  34.   tcpServer.Stop();
  35.  }


 
Dans l'initialisation de textbox1 :
 

Code :
  1. this.textBox1.Text = "K:\\Documents and Settings\\Administrator.MANGA-TORII\\My Documents\\CD\\01.mp3";


 
 
Client :

Code :
  1. private void button1_Click(object sender, System.EventArgs e)
  2.  {
  3.   const int BUFFER_SIZE = 1048576;
  4.   byte[] contenu = new byte[BUFFER_SIZE];
  5.   int buff_size;
  6.   System.Net.Sockets.TcpClient tcpClient = new System.Net.Sockets.TcpClient();
  7.   System.IO.FileStream fichier = new System.IO.FileStream("c:\\toto.mp3", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None, BUFFER_SIZE, false);
  8.   tcpClient.ReceiveBufferSize = BUFFER_SIZE;
  9.   tcpClient.Connect("localhost", 11000);
  10.   System.Net.Sockets.NetworkStream donnees = tcpClient.GetStream();
  11.   while (donnees.DataAvailable)
  12.   {
  13.    buff_size = BUFFER_SIZE;
  14.    donnees.Read(contenu, 0, buff_size);
  15.    fichier.Write(contenu, 0, buff_size);
  16.   }
  17.   tcpClient.Close();
  18.   fichier.Close();
  19.  }

Reply

Marsh Posté le 02-04-2003 à 22:43:00    

T'ain y'a des fois, je me dis que je suis trop une brute :D
 
Ma première appli qui utilise des socks [ : petite_larme ] :D
 
PS: Cherche pas à comprendre les commentaires, c'est des bouts résiduels de mes bugs, et des bouts d'exemples dont je me suis basé ;)
 
PS: ça marche bien, je m'ensuis servi pour déplacer d'un disque à l'autre (super utile les socks pour ça :D) un fichier JPG de taille inférieure au buffer, un MP3 de taille 1 fois suppérieure au buffer, et un DivX un peu énorme. Tout est passé.
 
dernier PS : cherche pas à comprendre pkoi j'envoie par morceaux, et que je lis/écrit aussi par morceaux dans le fichier. d'après la doc, la couche socks de windows s'en charge, mais j'aime pas, je préfère lire par petits bouts, ça évite entre autre d'avoir des tableaux de byte en mémoire de 800 Mo (pour mon divx par exemple... 2x 800 Mo, j'aurais presque saturé ma RAM :ouch:)


Message édité par MagicBuzz le 02-04-2003 à 22:50:41
Reply

Marsh Posté le 02-04-2003 à 22:58:57    

marchi, j'va tester ca demain et je te tiens au courant  :bounce:

Reply

Marsh Posté le 03-04-2003 à 12:21:11    

ToxicAvenger a écrit :

marchi, j'va tester ca demain et je te tiens au courant  :bounce:  


 
je t'ai envoyé un PM  :cry:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed