我使用StreamWriter
实例化Tcpstream
像这样
streamWriter = new StreamWriter(tcpClient.GetStream());
我对以下有关例外的调用的行为感到困惑。预计以下两个函数会引发IOException
令人惊讶的是,当IOException
所连接的服务器断开连接时,它们不会引发tcpClient
,因此底层的TCP客户端连接已断开。这两行执行时不会引发任何异常。为什么?
streamWriter.WriteLine(strBuffer);
streamWriter.Flush();
编辑:除了专家的回复之外,这篇特别的帖子也帮助我理解了原因。
http://social.msdn.microsoft.com/Forums/sk/netfxnetcom/thread/b177a935-7430-4812-9555-f747748df1af
本质上,当调用StreamWriter的WriteLine时,会调用NetworkStream.Write。这将写入外出缓冲区并在不阻塞的情况下返回,除非缓冲区已满。由OS维护的内部缓冲区包含未发送的数据,操作系统将继续尝试发送,直到给定次数的尝试失败。
WriteLine将抛出IOException,但不一定每次都抛出..
答案 0 :(得分:2)
此问题与StreamWriter
无关,只与NetworkStream
的行为有关。
NetworkStream.Flush()
是无操作。特别是在收件人确认在刷新之前发送的所有字节之前不会阻塞。
Flush方法实现了Stream.Flush方法;但是,由于NetworkStream没有缓冲,因此对网络流没有影响。调用Flush方法不会抛出异常。
(来自NetworkStream.Flush Method (MSDN))
你会在某个时候得到你的例外,但这可能会更晚。基本上,NetworkStream
和操作系统都不知道TCP连接已经中断,因此它们不会引发异常。
答案 1 :(得分:1)
这是TCP的核心方面,TCP是一种承诺通过网络可靠地将数据传输到另一台机器的协议。操作系统的工作是确保数据实际上在另一台机器上结束。在您编写数据很久之后,它会尝试多次获取数据,如果没有得到确认,则在必要时重新发送IP数据包。断开机器时会出现这种情况。经过多次重新尝试后,它不会放弃这样做。它可以在它放弃前一分钟。
本合同中隐含的内容是该连接在您的最终被认为是可靠的。您编写的任何内容最终都位于内核内存池中的缓冲区中。这个缓冲区大大提高了程序的吞吐量,消除了程序和可变传输速率之间的松弛。一旦它在缓冲区中,操作系统就有责任确保实际发送数据。
你可以看到这种情况发生了变化,直到以后才能从断开连接中获得异常。当缓冲区太满时,它可能发生在任何后续的Write()尝试中。它可能会一直延迟到调用套接字的Close()方法。