C#Networkstream.read()

时间:2009-09-01 22:43:52

标签: c# .net sockets

read(缓冲区,偏移量,长度)如何实际工作,如果我将长度读取为32,这是否意味着它会一直阻塞直到它收到32个字节?

我理解它会在套接字异常或连接关闭的情况下返回异常或0。

如果发送方只发送31个字节,会读取继续阻塞怎么办? 如果这是真的,是否意味着read总是返回等于传递给它的长度的整数?如果剩余的1个字节在一定时间后没有出现,那么cnan如何控制超时。

重要且尚未回答

相比之下,如果发送方发送32字节,那么确保读取将被阻塞,直到收到所有32个字节,或者它可以在不读取所有32个字节的情况下出现。

3 个答案:

答案 0 :(得分:6)

不,它不会阻止。 Read操作读取尽可能多的数据,最多可达size参数指定的字节数。 资料来源:http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspx

鉴于它不会等待额外的1个字节,如果你期望它,你应该实现一个循环来继续读取流。你可以退出循环,但感觉最好。


更新: 当我说“根本没有阻塞时,我错了。如果没有可用于读取的数据,Read方法返回0”,但是当我说它不会阻止等待填充整个缓冲区时,我是正确的这是Kazoom的问题所描述的场景。

更新以演示NetworkStream.Read阻塞等待第一个字节,但不阻止等待填充整个缓冲区

创建控制台项目

一方面,你有听众:


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();

另一方面,我们只发送一个字节:


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();

双方都会一直运行,直到他们到达Console.Read()。请注意,侦听器不会阻止Read。

听众将打印“1”

答案 1 :(得分:2)

它会阻塞,直到收到32个字节,或者连接关闭。应使用异步方法BeginRead()和EndRead()来提供非阻塞读取。

以下是一些清楚地展示阻止效果的示例代码。

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

修改

即使此代码产生阻塞效果,也只是因为NetworkStream的Stream's abstract Read() method实现(必须覆盖)。 Stream.Read()的文档说明了这一点:

  

实现返回的数量   字节读取。返回值为零   只有当前位置在   流的结束。

这就是为什么代码在没有收到数据时阻塞,并且还没有到达流的末尾。它还接着说:

  

实施将阻止直到   至少一个字节的数据可以   如果没有数据,请阅读   可用。读取时仅返回0   流中没有更多数据   并且不再期待(例如a   关闭套接字或文件结尾)。 <强>一种   实施可以免费返回更少   字节比请求即使结束   尚未到达流。

答案 2 :(得分:1)

关于超时的问题似乎仍然没有答案。

答案是你可以设置stream.ReadTimeout和stream.WriteTimeout,其中stream是你的NetworkStream对象。这样可以处理完全没有响应的阻塞情况。如果不设置这些值,流将无限期地等待。