.NET阻塞套接字读取直到X字节可用?

假设我在TCP上实现了简单的协议,其中每条消息由以下内容组成:

  1. 指示数据长度的int
  2. 二进制数据,长度为1。

阅读这样的消息,我想要像:

 int length = input.ReadInt(); byte[] data = input.ReadBytes(length); 

使用Socket.ReceiveNetworkStream.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); }