将分块数据从Socket接收到单个缓冲区

时间:2009-05-03 04:46:39

标签: c# sockets buffer

我正在尝试使用套接字编写一个简单的SNPP(简单网络分页协议)客户端。除了服务器之间的小的不一致之外,一切似乎都运行良好。

当我发送命令时,我需要读取回复,这通常是一个数据块。但是,Sprint的SNPP服务器分两部分发送回复。第一个数据块是状态代码的第一个数字。第二个块是剩余部分。例如,当我尝试接收“220 Gateway ready”回复时,它会像这样到达:

2

我必须发送另一个空命令来检索其余部分:

20 Gateway ready

目前,我正在使用:

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

如何在发出命令后确保收到所有可用数据,而不为每个数据块分配单独的缓冲区?

5 个答案:

答案 0 :(得分:3)

对于分块响应,我建议你阅读这样的数据:

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

答案 1 :(得分:1)

尝试检查Socket.Available属性以确定是否需要再次调用Receive。

答案 2 :(得分:0)

我想我理解你的问题。 Socket.Receive的重载允许您传递一个整数来指定偏移位置以开始放置数据。如果你得到1个字节,在你的例子中的第一个调用,你可以调用这个重载,偏移量为1并使用相同的缓冲区。

答案 3 :(得分:0)

Socket.Receive返回一个整数,它是接收的字节数。您可以检查这是否为1并再次致电Receive

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

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

答案 4 :(得分:-1)

所有

当Web服务器以“块”发送数据时,它在每个块之前都有它的长度(作为表示十六进制值的字符串)。

块大小[;块的扩展] 块数据

例如:to chunk 15 bytes:

F; 123456789ABCDEF

从Socket接收HTTP数据的最大问题是确定要读取多少数据:如果您已收到所有可用数据并再次调用Recieve方法,则Recieve方法将阻塞,直到远程套接字发送更多数据,这对于HTTP / 1.0连接永远不会发生。

你需要实现一个包裹套接字的阅读器;它应该将数据接收到缓冲区,并提供一个“ReadLine”方法,读取缓冲区的内容,直到它读取13后跟10(CRLF)