C # SocketAsyncEventArgs handles receiving and sending data

I am trying to understand the SocketAsyncEventArgs class in C #. http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

I follow this guide: http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

Now I am fixated on how I should process data from my server. What I'm trying to do is use SocketAsyncEventArgs for a connected client with 512 bytes allocated buffer space in BufferManager. Then I want to decode byte [] data into my own custom class (ClientPacket), which contains bytes [] for decoding and reading.

This is all good, but my server does not always respond with data, the question is:

I use 1 SocketAsyncEventArgs to receive and process a loop to process received data, and then allocates SocketAsyncEventArgs from the pool whenever I need to send and then return it after completion?

And how does SocketAsyncEventArgs know when the read is complete? (when it is finished with byte [] of the buffer before it overwrites it with new data), how, how does it return to the pool, when is this done if I do not respond?

+7
source share
1 answer

I use only one instance of SocketAsyncEventArgs for all my needs. I simply reset the buffer between each request (by setting it to a new byte []).

As soon as I connect and have a link to Socket, I start listening like this:

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

I have a helper function that flushes a buffer:

 private void ResetBuffer(SocketAsyncEventArgs e) { var buffer = new Byte[SocketBufferSize]; e.SetBuffer(buffer, 0, SocketBufferSize); } 

I process data such as:

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

In ProcessData, you can use an array of bytes as needed to pull data. I use it to create a MemoryStream, which I then deserialize into my class (like ClientPacket) as follows:

 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 } } 

Regarding your last question. The structure handles everything related to the basic TCP protocol, etc. Therefore, you can rely on an event handler that is called whenever there is data to process. Use the e.BytesTransferred value to indicate the amount of data actually received, which may be less, but will never exceed the size of your buffer (SocketBufferSize in my code). If the message was larger than the buffer size, the TCP infrastructure will buffer the messages and send them to you in pieces based on SocketBufferSize (by creating an event once for each fragment). If this is a concern, simply increase the SocketBufferSize until most of your message is received in a single fragment.

The disadvantage of fragmentation is that messages can be combined by infrastructure, which means you may need a way to tell when the first message ended. Typical approaches include prefilling your message with a 4-byte integer that indicates the length of the message. If necessary, I can develop more.

Hope this helps.

+8
source

All Articles