简体   繁体   中英

C# Networkstream.read()

How does read(buffer, offset, length) actually work, if i pass the length to read as 32, does that mean that it would keep blocking till it receives the 32 bytes?

I understand it would return and exception or 0 in case of socket exception or if the connection is closed, respectively.

what if the sender only sends 31 bytes , would read continue to block? if that is true, does it mean that read would always return the integer that is equal to length passed to it? and also how cnan i control the timeout if the remaining 1 byte does not come after certain time.

Important and yet not answered

In contrast, what if the sender sends 32 byte , does that assure that read would block until all 32 are received or can it come out without reading all the 32 bytes.

No, it will not block. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. Source: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspx

Given it will not wait for that extra 1 byte, if you are expecting it, you should implement a loop to continue reading the stream. You can exit the loop however you feel best.


UPDATE: I was wrong when I stated "There's no blocking at all. If no data is available for reading, the Read method returns 0", but I was correct when I stated that it wouldn't block waiting to fill the entire buffer which it the scenario described in Kazoom's question.

Updated to demonstrate that NetworkStream.Read blocks waiting for the first byte, but does not block waiting to fill the entire buffer .

Create to console projects

On one end, you have the listener:


IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
TcpListener listener = new TcpListener(ep);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream s = client.GetStream();
byte[] buffer = new byte[32];
Console.WriteLine(s.Read(buffer, 0, 32));
Console.WriteLine("Press any key to continue...");
Console.Read();

On the other end, we send only one byte:


IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
TcpClient client = new TcpClient();
client.Connect(ep);
client.GetStream().Write(new byte[] { 60 }, 0, 1);
Console.WriteLine("Press any key to continue...");
Console.Read();

Both sides will run until they reach Console.Read(). Notice that the listener does not block on Read.

The listener will print "1"

It will block until it receives 32 bytes, or the connection is closed. The async methods BeginRead() and EndRead() should be used to provide non-blocking reads.

Here is some example code clearly demonstrating the blocking effect.

   Socket one = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    Socket two = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);

    one.Bind(ep);
    one.Listen(1);
    two.Connect("127.0.0.1", 12345);
    one = one.Accept();

    NetworkStream s = new NetworkStream(two);
    byte[] buffer = new byte[32];
    s.Read(buffer, 0, 32);

Edit

Even though this code produces the blocking effect, it's only because of NetworkStream's implementation of Stream's abstract Read() method (which must be overridden). The documentation on Stream.Read() states this:

Implementations return the number of bytes read. The return value is zero only if the position is currently at the end of the stream.

Which is why the code blocks when NO data has been received AND the end of the stream has not been reached. It also goes on to say:

The implementation will block until at least one byte of data can be read , in the event that no data is available. Read returns 0 only when there is no more data in the stream and no more is expected (such as a closed socket or end of file). An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached.

The question about the timeout would appear to still be unanswered.

The answer is that you can set stream.ReadTimeout and stream.WriteTimeout, where stream is your NetworkStream object. This handles the blocking case of no response at all. Without setting these values, the stream will wait indefinitely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM