通过DataReader读取未知长度

时间:2015-02-06 20:34:45

标签: c# sockets

我最近在c#中使用windows app store编程,我遇到了套接字问题。 我需要能够从DataReader()读取未知长度的数据。

这听起来很简单,但经过几天的搜索后我找不到解决方案。

这是我当前的接收代码(有点草率,需要在我找到解决此问题的方法后进行清理。是的,这有点来自Microsoft的例子)

DataReader reader = new DataReader(args.Socket.InputStream);
try
{
    while (true)
    {
        // Read first 4 bytes (length of the subsequent string).
        uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
        if (sizeFieldCount != sizeof(uint))
        {
            // The underlying socket was closed before we were able to read the whole data.
            return;
        }

        reader.InputStreamOptions

        // Read the string.
        uint stringLength = reader.ReadUInt32();
        uint actualStringLength = await reader.LoadAsync(stringLength);
        if (stringLength != actualStringLength)
        {
            // The underlying socket was closed before we were able to read the whole data.
            return;
        }

        // Display the string on the screen. The event is invoked on a non-UI thread, so we need to marshal
        // the text back to the UI thread.
        //MessageBox.Show("Received data: " + reader.ReadString(actualStringLength));
        MessageBox.updateList(reader.ReadString(actualStringLength));
    }
}
catch (Exception exception)
{
    // If this is an unknown status it means that the error is fatal and retry will likely fail.
    if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
    {
        throw;
    }

    MessageBox.Show("Read stream failed with error: " + exception.Message);
}

1 个答案:

答案 0 :(得分:2)

你走的是正确的行 - 读取第一个INT以找出要发送的字节数。

Franky Boyle是正确的 - 如果没有信令机制,就不可能知道流的长度。这就是为什么它被称为流!

没有套接字实现(包括WinSock)将足够聪明地知道客户端何时完成数据发送。客户可能会在发送数据的过程中喝一杯茶!

您的服务器及其套接字永远不会知道!他们将要做什么?永远等待?我想他们可以等到客户端'关闭'连接?但是你的客户端可能有一个蓝屏,服务器永远不会得到那个TCP关闭数据包,它只会坐在那里认为它有一天会获得更多数据?

我从未使用过DataReader - 我从来没有听过那个类!改为使用NetworkStream。


从我的记忆中,我过去曾编写过这样的代码。我只是打字,没有检查语法。

using(MemoryStream recievedData = new MemoryStream())
{
    using(NetworkStream networkStream = new NetworkStream(connectedSocket))
    {
        int totalBytesToRead = networkStream.ReadByte();
        // This is your mechanism to find out how many bytes
        // the client wants to send.

        byte[] readBuffer = new byte[1024]; // Up to you the length!



        int totalBytesRead = 0;
        int bytesReadInThisTcpWindow = 0;
        // The length of the TCP window of the client is usually
        // the number of bytes that will be pushed through
        // to your server in one SOCKET.READ method call.


        // For example, if the clients TCP window was 777 bytes, a:

        // int bytesRead = 
        //          networkStream.Read(readBuffer, 0, int.Max);

        //    bytesRead would be 777.

        // If they were sending a large file, you would have to make
        // it up from the many 777s.

        // If it were a small file under 777 bytes, your bytesRead
        // would be the total small length of say 500.

        while
        (
            (
                bytesReadInThisTcpWindow =
                      networkStream.Read(readBuffer, 0, readBuffer.Length)
            ) > 0
        )
            // If the bytesReadInThisTcpWindow = 0 then the client
            // has disconnected or failed to send the promised number
            // of bytes in your Windows server internals dictated timeout
            // (important to kill it here to stop lots of waiting
            // threads killing your server)
        {
            recievedData.Write(readBuffer, 0, bytesReadInThisTcpWindow);
            totalBytesToRead = totalBytesToRead + bytesReadInThisTcpWindow;
        }

        if(totalBytesToRead == totalBytesToRead)
        {
            // We have our data!
        }
    }
}