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

时间:2011-07-22 16:41:21

标签: c# .net sockets networkstream

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

  1. int表示数据长度。
  2. 二进制数据,长度为1。
  3. 阅读这样的消息,我想要像:

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

    使用Socket.ReceiveNetworkStream.Read读取可用的字节数。我希望对ReadBytes的调用阻止,直到length字节可用。

    是否有一种简单的方法可以执行此操作,而无需循环读取,在等待剩余数据的偏移处重新启动?

    在实际的应用程序中,读取应该可以在异步或后台线程上完成,但我暂时忽略了它。重要的是能够在所有数据都可用之前完成读取。

    修改

    我知道我可以自己缓冲数据,我知道如何做到这一点。它只是围绕Receive的循环,在下一个偏移处继续。 我要求的是,如果有一个可重用的实现这样的循环,而不需要任何类型的自有循环(或者可重用的Async实现,当所有数据都可用时完成)。

6 个答案:

答案 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)

好吧,有点臭我们必须写一个循环,但我本来希望如果有人在这个论坛帖子中放一个循环所以我可以快速剪切和粘贴...这里是我的(是的,我我宁愿及时建立的东西,但它只适用于单元测试,他们控制模拟服务器,所以我不在乎这个+我不希望我的单元测试在调用我的Read方法时遇到失败)< / p>
        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);
        }