将分块数据从Socket接收到单个缓冲区
我正在尝试使用套接字编写一个简单的SNPP(简单网络分页协议)客户端。 除了服务器之间的小的不一致之外,一切似乎都运行良好。
当我发送命令时,我需要读取回复,这通常是一块数据。 但是,Sprint的SNPP服务器分两部分发送回复。 第一个数据块是状态代码的第一个数字。 第二个块是剩余部分。 例如,当我尝试接收“220 Gateway ready”回复时,它会像这样到达:
2
我必须发送另一个空命令来检索其余的:
20 Gateway ready
目前,我正在使用:
byte[] buffer = new byte[256]; socket.Receive(buffer);
如何在发出命令后确保收到所有可用数据而不为每个数据块分配单独的缓冲区?
对于chunked响应,我建议你阅读这样的数据:
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() ... }
尝试检查Socket.Available属性以确定是否需要再次调用Receive。
我想我理解你的问题。 Socket.Receive的这个重载允许您传递一个整数来指定一个偏移位置来开始放置数据。 如果您有1个字节,在第一次调用时,如示例所示,您可以使用偏移量1调用此重载并使用相同的缓冲区。
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);
所有,
当Web服务器以“块”发送数据时,它在每个块之前具有它的长度(作为指示hex值的字符串)。
chunk-size [; chunk-extensions]块数据
例如:要块15个字节:
F; 123456789ABCDEF
从Socket接收HTTP数据的最大问题是确定要读取的数据量:如果您已收到所有可用数据并再次调用Recieve方法,则Recieve方法将阻塞,直到远程套接字发送更多数据, HTTP / 1.0连接永远不会发生。
你需要实现一个包裹套接字的阅读器; 它应该将数据接收到缓冲区中,并提供一个“ReadLine”方法,该方法读取缓冲区的内容,直到它读取13后跟10(CRLF)