我正在尝试使用套接字编写一个简单的SNPP(简单网络分页协议)客户端。除了服务器之间的小的不一致之外,一切似乎都运行良好。
当我发送命令时,我需要读取回复,这通常是一个数据块。但是,Sprint的SNPP服务器分两部分发送回复。第一个数据块是状态代码的第一个数字。第二个块是剩余部分。例如,当我尝试接收“220 Gateway ready”回复时,它会像这样到达:
2
我必须发送另一个空命令来检索其余部分:
20 Gateway ready
目前,我正在使用:
byte[] buffer = new byte[256];
socket.Receive(buffer);
如何在发出命令后确保收到所有可用数据,而不为每个数据块分配单独的缓冲区?
答案 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)