假设我在TCP上实现了简单的协议,其中每条消息由以下内容组成:
int
表示数据长度。阅读这样的消息,我想要像:
int length = input.ReadInt();
byte[] data = input.ReadBytes(length);
使用Socket.Receive
或NetworkStream.Read
读取可用的字节数。我希望对ReadBytes
的调用阻止,直到length
字节可用。
是否有一种简单的方法可以执行此操作,而无需循环读取,在等待剩余数据的偏移处重新启动?
在实际的应用程序中,读取应该可以在异步或后台线程上完成,但我暂时忽略了它。重要的是能够在所有数据都可用之前完成读取。
我知道我可以自己缓冲数据,我知道如何做到这一点。它只是围绕Receive
的循环,在下一个偏移处继续。 我要求的是,如果有一个可重用的实现这样的循环,而不需要任何类型的自有循环(或者可重用的Async实现,当所有数据都可用时完成)。
答案 0 :(得分:5)
我相信BinaryReader.Read
将继续循环,直到它的读取次数与您要求的一样多或者在流的末尾点击,但假设您希望在到达结束时抛出异常流,我写个人写一个单独的方法。毕竟,在一个地方实施并重复使用很容易。
答案 1 :(得分:0)
Socket.Available
可以解决这个问题,如果你不介意等待的紧密循环?
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.available%28VS.71%29.aspx
答案 2 :(得分:0)
你需要自己缓冲数据,read的规格是它可以在1字节和缓冲区大小之间读取任何数量。
答案 3 :(得分:0)
查看以下链接: http://blog.stephencleary.com/2009/04/tcpip-net-sockets-faq.html
在此链接中,您可以找到关于套接字和库的优秀信息。
我要确保实现的一件事就是超时机制 避免在网络出现问题时卡住。
答案 4 :(得分:0)
听起来像yield语句可以很好地适应这种情况。
即。假设有一个循环观察输入流,并且一旦你达到每个长度数,你通过'yield'向IEnumerable / foreach返回对调用者的控制。
也许产量可能反过来通过事件发出信号,以便与IEnumerable进行替代解耦。我觉得IEnumerable很方便。
答案 5 :(得分:-1)
int numBytes = 0;
int i = 0;
while(numBytes != length)
{
numBytes += latestClient.Receive(body, numBytes, length-numBytes, SocketFlags.None);
if(i == 10000)
throw new Exception("Could not read enough data. read="+numBytes+" but expected="+length);
}