简体   繁体   English

C#Networkstream.read()

[英]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? read(缓冲区,偏移量,长度)如何实际工作,如果我将长度读取为32,这是否意味着它将保持阻塞直到它收到32个字节?

I understand it would return and exception or 0 in case of socket exception or if the connection is closed, respectively. 我知道它会返回异常,或者在套接字异常或连接关闭的情况下分别为0或0。

what if the sender only sends 31 bytes , would read continue to block? 如果发送方只发送31个字节,会读取继续阻塞吗? if that is true, does it mean that read would always return the integer that is equal to length passed to it? 如果这是真的,是否意味着read总是返回等于传递给它的长度的整数? and also how cnan i control the timeout if the remaining 1 byte does not come after certain time. 以及如果在一定时间后没有剩下的1个字节,我如何控制超时。

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. 相反,如果发送方发送32字节,那么确保读取将阻塞直到所有32个接收到,或者它可以在不读取所有32个字节的情况下出现。

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. Read操作读取尽可能多的数据,最多可达size参数指定的字节数。 Source: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspx 来源: 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. 鉴于它不会等待额外的1个字节,如果你期望它,你应该实现一个循环来继续读取流。 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. 更新:当我说“根本没有阻塞时,我错了。如果没有可用于读取的数据,Read方法返回0”, 但当我声明它不会阻止等待填充整个缓冲区时我是正确的它是Kazoom问题中描述的场景。

Updated to demonstrate that NetworkStream.Read blocks waiting for the first byte, but does not block waiting to fill the entire buffer . 更新以演示NetworkStream.Read阻塞等待第一个字节,但不阻止等待填充整个缓冲区

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(). 双方都会一直运行,直到他们到达Console.Read()。 Notice that the listener does not block on Read. 请注意,侦听器不会阻止Read。

The listener will print "1" 听众将打印“1”

It will block until it receives 32 bytes, or the connection is closed. 它将阻塞,直到它收到32个字节,或者连接关闭。 The async methods BeginRead() and EndRead() should be used to provide non-blocking reads. 应使用异步方法BeginRead()和EndRead()来提供非阻塞读取。

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). 尽管这段代码产生了阻塞效果,但这只是因为NetworkStream实现了Stream的抽象Read()方法 (必须重写)。 The documentation on Stream.Read() states this: Stream.Read()上的文档说明了这一点:

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). 只有当流中没有更多数据并且不再需要更多数据(例如关闭的套接字或文件末尾)时,read才返回0。 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. 答案是你可以设置stream.ReadTimeout和stream.WriteTimeout,其中stream是你的NetworkStream对象。 This handles the blocking case of no response at all. 这样可以处理完全没有响应的阻塞情况。 Without setting these values, the stream will wait indefinitely. 如果不设置这些值,流将无限期地等待。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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