Receiving chunked data from a Socket to a single buffer

廉价感情. 提交于 2019-12-23 05:13:24

问题


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?


回答1:


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() ...
}



回答2:


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




回答3:


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.




回答4:


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);



回答5:


All,

When a web-server is sending data in "chunks" it precedes each chunk with it's length (as a string indicating the hex value).

chunk-size[;chunk-extensions] chunk-data

eg: to chunk 15 bytes:

F; 123456789ABCDEF

The biggest issue with receiving HTTP data from a Socket is determining how much data to read: if you have received all the available data and call the Recieve method again, then the Recieve method will block until the remote socket sends more data, which for a HTTP/1.0 connection will never happen.

You need to implement a reader that wraps around the socket; it should receive data into a buffer, and provide a "ReadLine" method that reads the contents of the buffer until it reads 13 followed by 10 (CRLF)



来源:https://stackoverflow.com/questions/816350/receiving-chunked-data-from-a-socket-to-a-single-buffer

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!