2011-08-24 16 views
6

Actualmente estoy probando una biblioteca de red C# administrada que he escrito y me he encontrado con un problema ocasional. Este problema se manifiesta como un bloque de 5000 ms muy consistente (siempre dentro de 30 ms) en networkstream.write() para quizás el 1% de todas las operaciones de envío. Esto se realiza en un entorno de prueba, todos se ejecutan localmente, utilizando exactamente el mismo tamaño de paquete (2 MB) cada vez. En el cliente final que continuamente escribo lo siguiente a un NetworkStream conectado:Networkstream.Write() Problema de bloqueo

tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length); 
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length); 

y en el extremo del servidor utilizo una lectura asíncrona a la espera de los datos. Una vez que aparecen los datos, uso un ciclo while sobre tcpClientNetworkStream.DataAvailable hasta que se hayan recibido todos los datos.

Soy consciente de que networkstream.write() puede bloquear si las memorias intermedias están llenos, pero si este es el problema que no puedo pensar en una manera más rápida de limpiar ellos en el lado del servidor (envío y recepción tamaños de búfer son por defecto a 8192 bytes). El hecho de que el bloque sea tan consistente parece muy extraño. Mi primer pensamiento fue posiblemente alguna forma de Thread.Sleep pero haciendo una búsqueda completa del proyecto no muestra ninguna. Si alguien pudiera ayudar a arrojar algo de luz sobre este tema, sería muy apreciado.

Marc

de edición para agregar: Un truco que parece hacer desaparecer el problema es el siguiente (aunque hay un rendimiento asociado afectado debido a la BlockCopy):

byte[] bytesToSend = new byte[headerBytes.Length + dataBytes.Length]; 
Buffer.BlockCopy(headerBytes, 0, bytesToSend, 0, headerBytes.Length); 
Buffer.BlockCopy(dataBytes, 0, bytesToSend, headerBytes.Length, dataBytes.Length); 
tcpClientNetworkStream.Write(bytesToSend, 0, bytesToSend.Length); 

edición en ADD2 : También he reproducido el problema mediante el uso de dos escrituras asíncronas con una señal de hilo entre las dos. Por el momento, la única solución que tengo es la operación de escritura individual como en la edición anterior.

edit to add3: Ok, otra solución posible a continuación. Todavía estoy interesado en saber por qué los sucesivos escriben ocasionalmente 'bloques' en la forma en que lo hace.

BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream); 
sendStream.Write(bytesToSend, 0, bytesToSend.Length); 
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length); 
sendStream.Flush(); 

edición en add4: Después de extensas pruebas más la solución en 'editar a Add3' no hace desaparecer el problema, sólo se reduce la aparición de alrededor de 0,1% de los envíos. Mucho mejor, pero lejos de ser resuelto. Reemplazaré la lectura asíncrona con una lectura de bloqueo al lado para ver si eso lo ordena, como sugiere PaulF.

+0

Publique más código, ¿de dónde provienen dataBytes? ¿Está almacenado en algún lugar? – EKS

+0

Paso un objeto de paquete a un método SendPacket() que contiene los métodos NetworkStream.Write() anteriores. Una vez que este objeto de paquete se crea fuera de SendPacket() contiene matrices de bytes para 'headerBytes' y 'dataBytes'. – MarcF

+0

Tengo curiosidad por saber si el problema persiste si usa lecturas sincrónicas (de bloqueo) en el lado del servidor. – PaulF

Respuesta

2

Ok, no hay respuestas específicas a esta pregunta, así que haré todo lo posible para proporcionar una pequeña conclusión. Mi mejor suposición es que este problema fue originado originalmente porque estaba llenando el buffer de tcp más rápido de lo que lo estaba limpiando. Si se llena el búfer, hay un tiempo de espera desconocido antes de intentar agregar más datos. Este problema quizás sea más evidente al enviar y recibir datos dentro de la misma máquina. Es importante recordar que el tamaño predeterminado del búfer de lectura en .net es de solo 8192 bytes, por lo que si escribe en fragmentos mucho más grandes, quizás considere aumentar el tamaño del búfer de lectura a algo más grande, como 512000 bytes. Sin embargo, esto en sí mismo causa otros problemas debido al gran montón de objetos, etc., pero potencialmente se debate sobre una cuestión diferente.

Cuestiones relacionadas