tags:

views:

529

answers:

4

I'm trying to write a simple SNPP (Simple Network Paging Protocol) client using sockets. Everything seems to be working well, except for a small inconsistency between servers.

When I send a command, I need to read the reply, which is usually a single chunk of data. However, Sprint's SNPP server sends replies in two parts. The first chunk of data is the first digit of the status code. The second chunk is the remainder. For example, when I attempt to receive the "220 Gateway ready" reply, it arrives like this:

2

I have to send another empty command to retrieve the rest:

20 Gateway ready

For the moment, I'm using:

byte[] buffer = new byte[256];
socket.Receive(buffer);

How can I make sure that I receive all of the available data after issuing a command without allocating a separate buffer for each chunk of data?

A: 

Try to check Socket.Available property to determine if do you need to call Receive again.

ssvinarenko
A: 

I think I understand your question. This overload of Socket.Receive allows you to pass an integer to specify an offset position to start placing data. If you got 1 byte, on the first call as in your example, you can call this overload with an offset of 1 and use the same buffer.

JP Alioto
A: 

Socket.Receive returns an integer that is the number of bytes that were received. You could check if this is 1 and call Receive again.

byte[] buffer = new byte[256];
int len = socket.Receive(buffer);

if (len == 1)
  socket.Receive(buffer, 1, buffer.Length - 1, SocketFlags.None);
Samuel
A: 

For chunked responses I would recommend you reading data like this:

using (var resultStream = new MemoryStream())
{
    const int CHUNK_SIZE = 2 * 1024; // 2KB, could be anything that fits your needs
    byte[] buffer = new byte[CHUNK_SIZE];
    int bytesReceived;
    while ((bytesReceived = socket.Receive(buffer, buffer.Length, SocketFlags.None)) > 0)
    {
        byte[] actual = new byte[bytesReceived];
        Buffer.BlockCopy(buffer, 0, actual, 0, bytesReceived);
        resultStream.Write(actual, 0, actual.Length);
    }

    // Do something with the resultStream, like resultStream.ToArray() ...
}
Darin Dimitrov
I like this solution because it handles chunks of all sizes. However, after receiving the first reply, the application stops responding until there is new data. The debugger shows that it hangs on the while condition.
David Brown