2013-09-02 2 views
0

Ce que je suis en train de faire est de reçu un grand nombre d'octets (sur les données 5MB) envoyées par le côté clientflux réseau collé sur stream.Read (octet [] octet, int offset, int size)

Ci-dessous le code où les données (octet []) est reçu

byte[] receivedBytesRaw = new byte[4000]; 
//first, initialize network stream 
NetworkStream stream = client.GetStream(); 
    //The bytesNeeded is the size of bytes which is a protocol sent by the client side indicating the size of byte which will be sent 
    int bytesNeeded = 4000; 
    int bytesReceived = 0; 
    do 
    { 
     int bytesRead = stream.Read(receivedBytesRaw, bytesReceived, bytesNeeded - bytesReceived); 
     networkValidation.addBytesToList(receivedBytesRaw, ref receivedBytes); 
     bytesReceived += bytesRead; 
    } while (bytesReceived < bytesNeeded); 

Mais maintenant, je suis coincé sur un problème:

Everytime lorsque les données arrivent, les boucles do en boucle pour la première fois, et la valeur de retour (i) est 26, puis il boucle à nouveau, cette fois, quand il va à " i = stream.Read(receivedBytesRaw, 0, receivedBytesRaw.Length);", le programme semble w J'aide le côté client à envoyer des données et n'a pas de réponse, aussi, quand je vérifie "receivedBytesRaw", les données étaient incomplètes, seulement les 13 premiers octets ont été reçus, l'espace restant dans le tableau d'octets reste null, et le stream.DataAvailable est faux

Pourquoi le côté serveur a-t-il reçu des données incomplètes? Note: lorsque je tente d'envoyer de petites données (une chaîne), il est ok

============================= ========================================

Edité

ci-dessous est le code côté client qui envoie des données:

private int sendData(byte[] dataSend, string IP, int portNumber) 
    { 
     TcpClient clientSide = new TcpClient(); 
     int result = -1; 
     try 
     { 
      clientSide.Connect(IP, portNumber); 
     } 
     catch (Exception ex) 
     { 
      return 2; 
     } 
     NetworkStream netStream = clientSide.GetStream(); 
     if (netStream.CanWrite) 
     { 
      byte[] replyMsg = new byte[1024]; 

      netStream.Write(dataSend, 0, dataSend.Length); 
      netStream.Flush(); 
      result = 0; 
     } 
     else 
     { 
      result = 1; 
     } 
     return result; 
    } 
+0

cand vous publiez le code du côté client?ils doivent être synchronisés sur la quantité de données envoyées –

+0

Veuillez voir mon code édité, j'ai testé le côté client et les données (tableau d'octets) envoyées sont correctes – User2012384

+1

Vous ne savez tout simplement pas quand arrêter en train de lire. TCP est un flux, pas un format de paquet. L'expéditeur n'indique pas le nombre d'octets qu'il va envoyer et ne ferme pas le socket. Donc, le récepteur sera inévitablement coincé dans la boucle. Corrigez cela en écrivant d'abord dataSend.Length. Le récepteur peut maintenant lire cela en premier et compter les octets. –

Répondre

1

Parce que c'est un flux, et peut être reçu partiellement. Êtes-vous sûr de toujours recevoir des paquets d'une taille de 2048 octets? Je pense que vous avez besoin d'un protocole de trame, essayez de créer un protocole comme, en écrivant la taille des données qui suivent.

exemple: (psuedo)

void SendData(byte[] data) 
{ 
    // get the 4 bytes of a int value. 
    byte[] dataLength = BitConverter.GetBytes(data.Lenght); 
    // write the length to the stream. 
    stream.Write(dataLength, 0, dataLength.Length); 
    // write the data bytes. 
    stream.Write(data, 0, data.Length); 
} 

void Receive() 
{ 
    // read 4 bytes from the stream. 
    ReadBuffer(buffer, 4); 
    // convert those 4 bytes to an int. 
    int dataLength = BitConverter.ToInt32(buffer, 0); 
    // read bytes with dataLength as count. 
    ReadBuffer(buffer, dataLength);  
} 

// read until the right amount of bytes are read. 
void ReadBuffer(byte[] buffer, int length) 
{ 
    int i = 0; 
    int bytesNeeded = length; 
    int bytesReceived = 0; 
    do 
    { 
     //read byte from client 
     int bytesRead = stream.Read(buffer, bytesReceived, bytesNeeded-bytesReceived); 
     bytesReceived += bytesRead; 
     // merge byte array to another byte array 
    } while (bytesReceived < bytesNeeded); // <- you should do this async. 
} 

Ceci est juste un exemple ..

+0

J'ai essayé votre méthode comme le montre le code ci-dessus, mais le résultat reste le même ... – User2012384

1

Une autre solution, vous pouvez essayer utilise lit async. J'ai créé une classe qui lit jusqu'à ce que tous les octets soient lus. Si ce n'est pas un problème que le dossier complet est lu, vous pouvez essayer ceci:

Exemple:

Cet exemple montre que vous pouvez lire un protocole simple. ReadPacket gère un message de longueur + données. Ainsi, l'expéditeur enverra d'abord une valeur int contenant la longueur des données qui suit. La méthode StartReading lit un nom de fichier et le type de fichier. Il va stocker jusqu'à 10mb max taille de fichier. Mais ce n'est pas conçu à l'origine pour recevoir des fichiers.

const int MaxFileSize = 10 * 1024 * 1024; 

private void Example() 
{ 
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    socket.Connect("localhost", 12345); 

    StartReading(socket); 
} 

private void StartReading(Socket socket) 
{ 
    ReadPacket(socket, (filenameData) => 
    { 
     if (filenameData.Count == 0) 
     { 
      // disconnected 
      return; 
     } 

     // parse the filename 
     string filename = Encoding.UTF8.GetString(filenameData.Array, filenameData.Offset, filenameData.Count); 
     Trace.WriteLine("Receiving file :" + filename); 

     ReadPacket(socket, (fileData) => 
     { 
      if (fileData.Count == 0) 
      { 
       // disconnected 
       return; 
      } 

      Trace.WriteLine("Writing file :" + filename); 

      // write to the file 
      using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write)) 
       stream.Write(fileData.Array, fileData.Offset, fileData.Count); 

      // start waiting for another packet. 
      StartReading(socket); 
     }); 
    }); 
} 

private void ReadPacket(Socket socket, Action<ArraySegment<byte>> endRead) 
{ 
    // read header. (length of data) (4 bytes) 
    EasySocketReader.ReadFromSocket(socket, 4, (headerBufferSegment) => 
    { 
     // if the ReadFromSocket returns 0, the socket is closed. 
     if (headerBufferSegment.Count == 0) 
     { 
      // disconnected; 
      endRead(new ArraySegment<byte>()); 
      return; 
     } 

     // Get the length of the data that follows 
     int length = BitConverter.ToInt32(headerBufferSegment.Array, headerBufferSegment.Offset); 

     // Check the length 
     if (length > MaxFileSize) 
     { 
      // disconnect 
      endRead(new ArraySegment<byte>()); 
      return; 
     } 

     // Read bytes specified in length. 
     EasySocketReader.ReadFromSocket(socket, length, (dataBufferSegment) => 
     { 
      // if the ReadFromSocket returns 0, the socket is closed. 
      if (dataBufferSegment.Count == 0) 
      { 
       endRead(new ArraySegment<byte>()); 
       return; 
      } 

      endRead(dataBufferSegment); 
     }); 

    }); 

} 

La classe EasySocketReader se trouvent sur mon blog: http://csharp.vanlangen.biz/network-programming/async-sockets/asyncsocketreader/

Le EasyPacketReader original se trouve ici: http://csharp.vanlangen.biz/network-programming/async-sockets/easypacketreader/

Pour la partie envoi, vous pouvez utiliser quelque chose comme ceci:

private void SendFile(Socket socket, string filename) 
{ 
    byte[] filenameData = Encoding.UTF8.GetBytes(filename); 
    socket.Send(BitConverter.GetBytes(filenameData.Length)); 
    socket.Send(filenameData); 

    int fileSize; 
    byte[] fileData; 

    using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) 
    { 
     fileSize = (int)stream.Length; 

     if (fileSize > MaxFileSize) 
      throw new ArgumentOutOfRangeException("File too big"); 

     fileData = new byte[fileSize]; 

     stream.Read(fileData, 0, fileSize); 
    } 

    socket.Send(BitConverter.GetBytes(fileSize)); 
    socket.Send(fileData); 
}