2009-09-10 7 views
1

Lors de la lecture des données sur le réseau, vous spécifiez un tampon pour recevoir les données en:Comment gérer les données de mise en mémoire tampon lues sur le réseau?

byte[] b = new byte[4096]; 
socket.Receive(b); 

Maintenant, ma première pensée est bien sûr de réutiliser le tampon de réception en déclarant comme une variable membre de la classe. Mon prochain problème est que je n'ai pas reçu toutes les données que je m'attends, donc j'ai besoin de tampon mes données. Cela est facile à accomplir en gardant la trace du nombre d'octets reçus, et en spécifiant le décalage: la question est ici

socket.Receive(m_ReceiveBuffer, count, m_ReceiveBuffer.Length - count); 

Maintenant, que si elle est toujours pas assez, je devine que je dois développer la tampon, ce qui signifie la copie de la mémoire, et continuer à recevoir dans ce tampon. En supposant que quelque chose se soit mal passé, ce tampon continuerait de croître, et si des messages suffisamment gros sont reçus, le système serait saturé de mémoire.

Des idées pour gérer correctement cela? Y a-t-il une meilleure façon de recevoir les données que de simplement remplir, copier, développer, remplir, copier, développer dont je parle?

Répondre

2

lecture en morceaux:

const int ChunkSize = 4096; 
int bytesRead; 
byte[] buffer = new byte[ChunkSize]; 
while ((bytesRead = socket.Receive(buffer, 0, ChunkSize, SocketFlags.None)) > 0) 
{ 
    byte[] actualBytesRead = new byte[bytesRead]; 
    Buffer.BlockCopy(buffer, 0, actualBytesRead, 0, bytesRead); 
    // Do something with actualBytesRead, 
    // maybe add it to a list or write it to a stream somewhere 
} 
+0

Cela ne résout toujours pas le problème où je ne peux pas traiter les données tout de suite, il continuera à remplir la mémoire. – esac

+0

Pourriez-vous expliquer ce que vous entendez par "traiter" les données? Ne pouvez-vous pas "traiter" les données en morceaux ou avez-vous besoin de lire toutes les données, auquel cas vous aurez besoin de les avoir en mémoire? –

1

Avant de commencer System.Net.Sockets.Socket, êtes-vous sûr que vous ne pouvez pas utiliser System.Net.Sockets.TcpClient (ou UdpClient) qui fait tout le Tampon désordonné fonctionne pour vous et le transforme en un flux facile à gérer? Si ce n'est pas le cas, n'oubliez pas que la quantité de données que vous recevez ne doit pas être égale à ce que vous demandez, vous devriez donc toujours regarder la valeur de retour de la fonction de réception. Et, la seule façon de ne pas manquer de mémoire est de traiter réellement ce que vous recevez.

+0

Oui, je n'utilise que Receive comme exemple, mais j'utilise l'API ReceiveAsync pour lire les données de manière asynchrone. Pour cela, un flux réseau ne fonctionnera pas pour mon cas. Et mon problème est que oui, cela fonctionne très bien si vous pouvez traiter toutes les données immédiatement, mais parfois, il suffit juste de le pousser à être un peu plus grand. – esac

0

D'abord, séparez le code pour recevoir les données et traiter les données. Le tampon de réception doit uniquement contenir les données jusqu'à ce que le code ait la possibilité de les copier dans la zone de traitement. La zone de traitement est l'endroit où vous déterminerez si vous avez reçu suffisamment de données pour faire quelque chose d'utile. Ne laissez pas les données dans le tampon de réception réseau jusqu'à ce que cela se produise. Pour le tampon de réception réseau, je pense que l'utilisation d'un tampon circulaire vous aidera avec votre idée de réutiliser un tampon. J'espère que vous avez une idée de la taille des messages. Cela aidera à déterminer la taille du tampon. Si vous affirmez (ou quelque chose de similaire) lorsque les pointeurs de lecture et d'écriture du tampon circulaire se rencontrent, augmentez la taille du tampon. Une fois que la taille de la mémoire tampon est suffisante, vous devriez pouvoir lire suffisamment de données dans le tampon à un rythme suffisamment rapide pour que le tampon circulaire ne déborde pas.

Questions connexes