How can I get Windows.Storage.Streams.IInputStream inputStream length?

315 Views Asked by At

I use HoloLens 2 as a client and my unity server on my PC. (More discussion about this: How can I read byte array coming from server in UWP app?) I lost my debug await reader1.LoadAsync(256);. I tried everything to get my stream data but I couldn't. I don't want to const value for the buffer I need the exact stream size for the buffer. I tested this and it works only and only if the buffer size and data stream size is equal. Or you can suggest me other approaches?

// Create the StreamSocket and establish a connection to the server.
        using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
        {
            // The server hostname that we will be establishing a connection to.
            var hostName = new Windows.Networking.HostName(host);

            // client is trying to connect...

            await streamSocket.ConnectAsync(hostName, port);

            // client connected! 

            // Read data from the server.
            using (Windows.Storage.Streams.IInputStream inputStream = streamSocket.InputStream)
            {
                using (var reader1 = new Windows.Storage.Streams.DataReader(inputStream))
                {
                    reader1.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.ReadAhead;
                    reader1.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                    reader1.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
                    
              
                    // Should be in stream size !!!
                    await reader1.LoadAsync(256);
                    
                    while (reader1.UnconsumedBufferLength > 0)
                    {
                        var bytes1 = new byte[reader1.UnconsumedBufferLength];
                        reader1.ReadBytes(bytes1);

                        // Handle byte array internally!
                        HandleData(bytes1);

                        await reader1.LoadAsync(256);
                    }
                    reader1.DetachStream();
                }
            }
        }
        // close socket
    }
    catch (Exception ex)
    {
        Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
    }
2

There are 2 best solutions below

0
On BEST ANSWER

Hi Nico sorry for the late update. I tried everything but TCP is nearly impossible for HoloLens with UWP app. So I tried UDP and it works perfectly (https://github.com/mbaytas/HoloLensUDP). I hope Microsoft put a TCP example for HoloLens 1 and 2 in near future.

0
On

How can I get Windows.Storage.Streams.IInputStream inputStream length?

IInputStream of SteamSocket can't be seek. So we can't get length of steam, That's why we need set a buffer to load input stream all the time until the stream finished.

I checked code above, if you have set InputStreamOptions as ReadAhead. It will do the next step, when the 256 buffer fills up, please try to InputStreamOptions as Partial.

reader1.InputStreamOptions = InputStreamOptions.ReadAhead;

Update

If you want to get length of current message before load it, we suggest you write the message length as message header into to the steam.

For example

string stringToSend = "PC client uses System.Net.Sockets.TcpClient, System.Net.Sockets.NetworkStream but UWP (HoloLens) uses Windows.Networking.Sockets.StreamSocket.";
var bytes = Encoding.UTF8.GetBytes(stringToSend);
writer.WriteInt32(bytes.Length);
writer.WriteBytes(bytes);

Receive client

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;
    }

    // Read the string.
    int bytesLength = reader.ReadInt32();
    uint Actualbytelength = await reader.LoadAsync((uint)bytesLength);
    if (Actualbytelength != bytesLength)
    {
        // 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.

    var bytes = new byte[Actualbytelength];
    reader.ReadBytes(bytes);

}