2012-01-26 10 views
7

Estoy tratando de entender la clase 'SocketAsyncEventArgs' en C#. http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspxC# SocketAsyncEventArgs que maneja los datos de recepción y envío

estoy siguiendo este tutorial: http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

Ahora estoy atascado en la forma en que exactamente debería procesar los datos con mi servidor. Lo que intento hacer es usar un SocketAsyncEventArgs para un cliente conectado con un espacio Buffer asignado de 512 bytes en el BufferManager. Entonces, lo que quiero hacer es decodificar los datos de byte [] en mi propia clase personalizada (ClientPacket) que contiene el byte [] para decodificar y leer.

Esto es todo bien pero mi servidor no siempre responde con los datos de la pregunta es:

hacer yo utilizo 1 SocketAsyncEventArgs para la recepción y el lazo alrededor de procesar recibir datos, a continuación, asignar una SocketAsyncEventArgs de la piscina siempre Necesito enviar y luego devolverlo al finalizar?

¿Y cómo sabe SocketAsyncEventArgs cuando se completa la lectura? (cuando finaliza con el búfer byte [] antes de que se sobrescriba con datos nuevos), por ejemplo, ¿cómo se devuelve al grupo cuando finaliza si no respondo?

Respuesta

8

Solo uso una instancia de SocketAsyncEventArgs para todas mis necesidades. Simplemente reinicié el búfer entre cada solicitud (configurándolo en un nuevo Byte []).

Una vez que he conectado y tener una referencia a la toma, comienzo a escuchar la siguiente manera:

public void StartListening(SocketAsyncEventArgs e) 
{ 
    ResetBuffer(e); 
    e.Completed += SocketReceive; 

    socket.ReceiveAsync(e); 
} 

que tienen una función auxiliar que restablece el búfer:

private void ResetBuffer(SocketAsyncEventArgs e) 
{ 
    var buffer = new Byte[SocketBufferSize]; 

    e.SetBuffer(buffer, 0, SocketBufferSize); 
} 

que procesar los datos como:

private void SocketReceive(Object sender, SocketAsyncEventArgs e) 
{ 
    ProcessData(e.Buffer, 0, e.BytesTransferred); 

    ResetBuffer(e); 

    socket.ReceiveAsync(e); 
} 

En ProcessData, puede utilizar la matriz de bytes según sea necesario para extraer los datos . Yo lo uso para crear un MemoryStream que luego Deserialize en mi clase (similar a ClientPacket), de la siguiente manera:

private void ProcessData(Byte[] data, Int32 count) 
{ 
    using (var stream = new MemoryStream(data, 0, count)) 
    { 
     var serializer = new XmlSerializer(typeof(ClientPacket)); 

     var packet = serializer.Deserialize(stream); 

     // Do something with the packet 
    } 
} 

En cuanto a su última pregunta. El marco maneja todo lo que tiene que ver con el protocolo TCP subyacente, etc. por lo que puede confiar en que se llame al controlador de eventos siempre que haya datos para procesar. Use el valor e.BytesTransferred para indicar la cantidad de datos que recibió, que pueden ser más pequeños que, pero nunca superarán, el tamaño del búfer (SocketBufferSize en mi código). Si el mensaje fue más grande que el tamaño del búfer, la infraestructura TCP almacenará los mensajes en búfer y se los enviará en fragmentos en base a SocketBufferSize (aumentando el evento una vez para cada fragmento). Si esto es una preocupación, simplemente aumente SocketBufferSize hasta que la mayoría de su mensaje se reciba en un solo fragmento.

La desventaja de la fragmentación es que los mensajes pueden ser fusionados por la infraestructura, lo que significa que es posible que necesite una forma de saber cuándo ha terminado el primer mensaje. Los enfoques típicos incluyen prefacturar su mensaje con un entero de 4 bytes que indica la longitud del mensaje. Puedo elaborar más si es necesario.

Espero que ayude.

+0

Dijiste estableciéndolo en un nuevo byte [], pero estoy compartiendo un gran bloque de búfer para todos los SocketAsyncEventArgs, si leo de ese bloque de búfer en un paquete, entonces el bloque de búfer podría sobrescribirse en la próxima entrada datos, incluso si copio la matriz de bytes [] va en contra usando el bloque de almacenamiento intermedio para enviar/recibir datos? Además, ¿cómo podría enviar datos con el mismo objeto cuando una operación de recepción podría suceder en cualquier momento? –

+1

Parece que asume una conexión de socket única entre 2 máquinas. No puede reutilizar solo un SocketAsyncEventArgs cuando maneje muchas conexiones simultáneas, que es de lo que creo que se trató la pregunta. (Y para qué es construido SocketAsyncEventArgs). –

+0

gracias SonOfPirate, Sería increíble si puede obtener más información sobre la recepción de gran cantidad de datos. especialmente, aclare por favor si debo volver a llamar a ReceiveAsync cada vez antes de llegar al final; o Framework lo hará por mí? –

Cuestiones relacionadas