设置 NetworkStream.ReceiveTimeout 不触发异常
这是这个问题的延续。我是网络编程的新手,所以我只是编写一些小示例来获得理解,但在解释结果方面有些困难。
当应该发送数据的客户端在发送所有预期数据之前关闭时,设置 NetworkStream.ReceiveTimeout 似乎无法正常工作。
以下是示例代码:
public static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 10001);
listener.Start();
ThreadPool.QueueUserWorkItem(WriterThread);
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
{
client.ReceiveTimeout = (int)new TimeSpan(0, 0, 2).TotalMilliseconds;
stream.ReadTimeout = (int)new TimeSpan(0, 0, 2).TotalMilliseconds;
ReceiveMessage(stream, 1024);
}
listener.Stop();
Console.WriteLine("Done.");
Console.ReadKey(true);
}
private static void WriterThread(object state)
{
using (TcpClient client = new TcpClient())
{
client.Connect(new IPEndPoint(IPAddress.Loopback, 10001));
using (NetworkStream stream = client.GetStream())
{
byte[] bytes = Encoding.ASCII.GetBytes("obviously less than 1024 bytes");
stream.Write(bytes, 0, bytes.Length);
Thread.Sleep(10000); // comment out
}
}
}
private static byte[] ReceiveMessage(Stream stream, int length)
{
byte[] buffer = new byte[length];
int bufferFill = 0;
while (true)
{
bufferFill += stream.Read(buffer, bufferFill, buffer.Length - bufferFill);
if (buffer.Length == bufferFill)
return buffer;
Thread.Sleep(100);
}
}
此版本可以正常工作,在 stream.Read()
调用上触发异常。但是,如果我注释掉 Thread.Sleep(10000),客户端会关闭连接,但侦听器无法识别它。主线程卡在 while(true) 循环内。 stream.Read()
不断返回零,但没有抛出异常。
这是正常的吗?如果是这样,我该如何处理异常的客户端断开连接?
This is a continuation of the this question. I am new to network programming, so I am just writing small sample stuff to gain understanding, but somewhat struggling with explaining results.
It seems setting NetworkStream.ReceiveTimeout
is not working correctly when client that was supposed to be sending data simply closes before sending all the expected data.
Here is the sample code:
public static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 10001);
listener.Start();
ThreadPool.QueueUserWorkItem(WriterThread);
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
{
client.ReceiveTimeout = (int)new TimeSpan(0, 0, 2).TotalMilliseconds;
stream.ReadTimeout = (int)new TimeSpan(0, 0, 2).TotalMilliseconds;
ReceiveMessage(stream, 1024);
}
listener.Stop();
Console.WriteLine("Done.");
Console.ReadKey(true);
}
private static void WriterThread(object state)
{
using (TcpClient client = new TcpClient())
{
client.Connect(new IPEndPoint(IPAddress.Loopback, 10001));
using (NetworkStream stream = client.GetStream())
{
byte[] bytes = Encoding.ASCII.GetBytes("obviously less than 1024 bytes");
stream.Write(bytes, 0, bytes.Length);
Thread.Sleep(10000); // comment out
}
}
}
private static byte[] ReceiveMessage(Stream stream, int length)
{
byte[] buffer = new byte[length];
int bufferFill = 0;
while (true)
{
bufferFill += stream.Read(buffer, bufferFill, buffer.Length - bufferFill);
if (buffer.Length == bufferFill)
return buffer;
Thread.Sleep(100);
}
}
This version works correctly triggering exception on the stream.Read()
call. However If I comment out Thread.Sleep(10000)
, the client closes connection, but listener fails to recognize it. Main thread gets stuck inside the while(true)
loop. The stream.Read()
keeps returning zero, but no exception thrown.
Is this normal? If so how am I expected to handle abnormal client disconnections?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这听起来很正常。由于客户端已断开连接,因此不会出现接收或读取超时。这意味着没有更多数据可供读取,并且流将立即返回 0,如记录的那样。
我会将您的 ReceiveMessage 方法修改为如下所示:
显然,如果在我们收到所有预期字节之前stream.Read() 调用返回 0,则一定存在某种形式的断开连接或类似情况。无论哪种方式,我们都不会从流中获取更多数据。
编辑: Stream 类没有“消息”的概念。如果缓冲区中尚无数据,则 Read 方法将阻塞,直到有更多数据可用为止。然而,当无法接收更多数据时,它将返回 0,在这种情况下意味着连接已关闭。
Yes, this sounds normal. There is no receive- or read timeout because the client has disconnected. This means that no more data is available for reading and the stream will return 0 immediately just as documented.
I would modify your ReceiveMessage method to something like the following:
Clearly if the stream.Read() call returns 0 before we have received all the expected bytes there must have been some form of disconnection or similar. Either way we will never get any more data from the stream.
Edit: The Stream class has no notion of a "message". The Read method blocks until more data becomes available if none is already in the buffer. It will however return 0 when no more data can be received, which in this case means the connection is closed.