C#NetworkStream.DataAvailable似乎不可靠

时间:2016-04-19 23:30:59

标签: c# sockets tcp networkstream

我有一个使用TCP套接字来交换字节数组的应用程序,在大多数情况下包含JSON字符串数据。我所经历的是,对于较大的消息和不太理想的网络条件,使用NetworkStream.DataAvailable似乎不是检测消息结束的可靠方法。似乎在某些情况下,即使只有部分消息已由对等方传输(使用TcpClient.GetStream().Write(data, 0, data.Length),DataAvailable也会设置为false。这导致不完整的数据被传递回应用程序,在JSON消息的情况下,意味着反序列化失败。

我尝试了两个具有相同问题的实现:

实施1:

byte[] Data;
byte[] buffer = new byte[2048];
using (MemoryStream ms = new MemoryStream())
{
    int read;

    while ((read = ClientStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        ms.Write(buffer, 0, read);
        BytesRead += read;

        if (!ClientStream.DataAvailable) break;
    }

    Data = ms.ToArray();
}

实施2:

byte[] Data;
using (MemoryStream ms = new MemoryStream())
{
    byte[] buffer = new byte[2048];

    do
    {
        int read = ClientStream.Read(buffer, 0, buffer.Length);
        if (read > 0)
        {
            ms.Write(buffer, 0, read);
            BytesRead += read;
        }
    }
    while (ClientStream.DataAvailable);

    Data = ms.ToArray();
}

似乎一个解决方案非常有效但完全不是最佳的是在NetworkStream.DataAvailable为false(在循环内部)的情况下添加Thread.Sleep以允许传递数据。然而,这严重限制了我想避免的整体IOPS,即

实施3(有效,但次优)

byte[] Data;
using (MemoryStream ms = new MemoryStream())
{
    byte[] buffer = new byte[2048];

    do
    {
        int read = ClientStream.Read(buffer, 0, buffer.Length);
        if (read > 0)
        {
            ms.Write(buffer, 0, read);
            BytesRead += read;
        }

        if (!ClientStream.DataAvailable) System.Threading.Thread.Sleep(250);
    }
    while (ClientStream.DataAvailable);

    Data = ms.ToArray();
}

我真的很想找到一种方法来保持循环,直到所有数据都传递完毕。正如我所提到的,我在客户端上从零到数据长度进行简单的写操作,所以我不认为那里存在问题。

之前有没有人有这样的经历和推荐?

1 个答案:

答案 0 :(得分:1)

似乎.DataAvailable确实是可靠的,因为数据通过网络到达的速度可能比从流中读取数据的速度慢,所以.DataAvailable可以在我的应用程序认为的开始和结束之间翻转一条消息。

我回答并关闭这个,因为我相信唯一的解决方案是:

1)添加一个超额接收超时值,并在读取循环中执行thread.sleep,并在达到接收超时后使操作到期

2)实现一些指示数据有效负载大小的机制 - 显式或通过创建元数据头系统 - 来指示应该读取多少数据,并在读取了大量数据或操作超时后退出

这两个是我能想到的最好的,似乎可以通过其他基于TCP的协议(如HTTP)和其他任何其他RPC来验证。

希望这可以节省一些时间。