locked
[UWP] LoadAsync() blocks forever in DataReader when reading StreamSocket RRS feed

  • Question

  • I'm trying to read TCP byte packets in UWP.

    Environment
    1. Windows 10, PC
    2. Visual Studio 2015

    My requirements
    1. I don't know the incoming packet length (no Length byte)
    2. Packet does not have unique START / END marker bytes
    3. Each packet can have different length
    4. Packet is a byte array

    Status of investigation
    1. TCP socket in this case is .NET native, so I can't debug it. No source code available.
    2. All examples I find, assumes first byte is a Length byte, so they now how much bytes to read. Or sending/reading string lines, that are delimited.

    Code description
    - as I don't know incoming packet size, I read in a loop until stream is empty (however it does not work)
    - I can't assume some big buffer size, like 20k bytes or so, because I don't know the length of incoming packet
    - when I set CHUNK_SIZE to uint.Max, there is MemoryOverflowException thrown (std::bad_alloc)
    - InputStreamOptions.Partial is enabled


    private StreamSocket _socket; public async Task<byte[]> Read() {        const uint chunkSize = 4;     var bytes = new List<byte>();     using (var reader = new DataReader(_socket.InputStream))     {    
    reader.InputStreamOptions = InputStreamOptions.Partial;
         await reader.LoadAsync(chunkSize);
         while (reader.UnconsumedBufferLength > 0)
         {
            var buffer = new byte[reader.UnconsumedBufferLength];
            reader.ReadBytes(buffer);
            bytes.AddRange(buffer);
                // here await blocks forever, when loading last chunk of bytes from the stream
           await reader.LoadAsync(chunkSize); // <-- BUG
         }
         reader.DetachStream();
        }

    return bytes.ToArray();
    }

    Current behavior
    Reading blocks on "await reader.LoadAsync()" method, when reading last chunk of message from socket stream.

    Correct behavior
    When the stream is empty, return from LoadAsync() method, with "reader.UnconsumedBufferLength = 0", so the reading loop finishes.

    Debug log

    DEV: Listening...
    DEV: Connecting...
    DEV: Connection received
    DEV: Connected
    DEV: Started reading...
    DEV: Sent 12 bytes: abcdefghijkl
    reader.UnconsumedBufferLength = 0 bytes
    AFTER reader.LoadAsync(count = 4 bytes)
    reader.UnconsumedBufferLength = 4 bytes
    ---------------------------------------
    reader.UnconsumedBufferLength = 4 bytes
    buffer.Length = 4 bytes
    reader.ReadBytes(buffer)
    buffer = abcd
    reader.UnconsumedBufferLength = 0 bytes
    BEFORE LoadAsync(count = 4 bytes)
    AFTER LoadAsync()
    ---------------------------------------
    reader.UnconsumedBufferLength = 4 bytes
    buffer.Length = 4 bytes
    reader.ReadBytes(buffer)
    buffer = efgh
    reader.UnconsumedBufferLength = 0 bytes
    BEFORE LoadAsync(count = 4 bytes)
    AFTER LoadAsync()
    ---------------------------------------
    reader.UnconsumedBufferLength = 4 bytes
    buffer.Length = 4 bytes
    reader.ReadBytes(buffer)
    buffer = ijkl // here is the last part of data from stream that was read, and we are done
    reader.UnconsumedBufferLength = 0 bytes
    BEFORE LoadAsync(count = 4 bytes) // however on this Load execution stops
    // here stops forever, until some other data is received (can be simulated, uncommenting second Send())






    • Edited by bing_case Thursday, July 28, 2016 1:31 PM
    Thursday, July 28, 2016 12:37 PM

Answers

  • It blocks because not enough bytes are available.

    There _HAS_ to be a terminator string or some indication of how big the stream is. Basically all internet based communication protocols send the length of the package beforehand, or the length is known in advance in the case of live media streams.

    • Marked as answer by bing_case Thursday, July 28, 2016 1:31 PM
    Thursday, July 28, 2016 12:41 PM