PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, October 22, 2022

[FIXED] How to read continuously and asynchronously from network stream using abstract stream?

 October 22, 2022     .net-standard-2.0, asynchronous, c#, networkstream, sockets     No comments   

Issue

Description

I would like to read asynchronously from a NetworkStream or SSLStream using their abstract Stream parent class. There are different ways to read asynchronously from stream:

  • Asynchronous Programming Model (APM): It uses BeginRead and EndRead operations.
  • Task Parallel Library (TPL): It uses Task and creates task continuations.
  • Task-based Asynchronous Pattern (TAP): Operations are suffixed Async and async and await keyword can be used.

I am mostly interested using the TAP pattern to achieve asynchronous read operation. Code below, asynchronously read to the end of stream and returns with the data as byte array:

    internal async Task<byte[]> ReadToEndAsync(Stream stream)
    {
        byte[] buffer = new byte[4096];
        using (MemoryStream memoryStream = new MemoryStream())
        {
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            while (bytesRead != 0)
            {
                // Received datas were aggregated to a memory stream.
                await memoryStream.WriteAsync(buffer, 0, bytesRead);
                bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            }

            return memoryStream.ToArray();
        }
    }

The buffer size is 4096kB. If the transferred data is more than the buffer size then it continues to read until 0 (zero), the end of the stream. It works with FileStream but it hangs indefinitely at the ReadAsync operation using NetworkStream or SslStream. These two stream behave differently than other streams.

The problem lies behind that the network stream ReadAsync will only return with 0 (zero) when the Socket communication is closed. However I do not want to close the communication every time a data is transferred through the network.

Question

How can I avoid the blocking call of the ReadAsync without closing the Socket communication?


Solution

I would like to read asynchronously from a NetworkStream or SSLStream using their abstract Stream parent class.

Do you really need to? TCP/IP socket communication is quite complex to do correctly. I strongly recommend self-hosting an HTTP API or something like that instead.

The problem lies behind that the network stream ReadAsync will only return with 0 (zero) when the Socket communication is closed.

Yes, and the code you posted only returns a result when the entire stream has been read.

So, what you need is a different return condition. Specifically, you need to know when a single message has been read from the stream. What you need is message framing, as described on my blog.

I also have some sample code on my blog showing one of the simplest message framing solutions (length prefix). Take careful note of the complexity and length of the simplest solution, and consider whether you really want to write socket-level code.

If you do want to continue writing socket applications, I recommend watching my YouTube series on asynchronous TCP/IP socket programming.



Answered By - Stephen Cleary
Answer Checked By - Senaida (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing