.NET阻塞套接字读取直到X字节可用?
假设我在TCP上实现了简单的协议,其中每条消息由以下内容组成:
- 指示数据长度的
int
。 - 二进制数据,长度为1。
阅读这样的消息,我想要像:
int length = input.ReadInt(); byte[] data = input.ReadBytes(length);
使用Socket.Receive
或NetworkStream.Read
读取可用的字节数。 我想要调用ReadBytes
来阻塞,直到length
字节可用。
是否有一种简单的方法可以执行此操作,而无需循环读取,在等待剩余数据的偏移处重新启动?
在一个真正的应用程序中,读取应该可以在异步或后台线程上完成,但我暂时忽略了它。 重要的是能够在所有数据都可用之前读取不完整。
编辑
我知道我可以自己缓冲数据,我知道如何做到这一点。 它只是一个循环Receive
继续下一个偏移。 我要求的是,如果有一个可重用的实现这样的循环 ,而不需要任何类型的自有循环(或者可重用的Async实现,当所有数据都可用时完成)。
某事,某处必须循环。 毕竟,可能需要多个套接字读取。
我相信BinaryReader.Read
将继续循环,直到它的读取量与您要求的一样多或者到达流的末尾,但假设您想要在流程结束时抛出exception,我会写个人写一个单独的方法。 毕竟,在一个地方实施并重复使用很容易。
Socket.Available
可以解决这个问题,如果你不介意等待的紧密循环?
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.available%28VS.71%29.aspx
您需要自己缓冲数据,读取的规范是它可以在返回时读取1个字节和缓冲区大小之间的任何数量。
听起来像yield语句可以很好地适应这种情况。
也就是说有一个循环观察输入流,并且一旦你点击每个长度数,你通过’yield’向IEnumerable / foreach返回对调用者的控制。
也许产量可以通过事件发出信号,以便与IEnumerable进行替代解耦。 我觉得IEnumerable很方便。
请查看以下链接: http : //blog.stephencleary.com/2009/04/tcpip-net-sockets-faq.html
在此链接中,您将找到有关套接字和库的优秀信息。
我要确保实现的一件事是超时机制,以避免在网络出现故障时卡住。
好吧,有点臭我们必须写一个循环,但我会喜欢,但如果有人在这个论坛post中放一个循环所以我可以快速剪切和粘贴它…这是我的(是的,我会的相当时间,但它只适用于unit testing,他们控制模拟服务器,所以我不在乎+我不希望我的unit testing在调用我的Read方法时遇到失败
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); }