为什么将StreamReader连接到NetworkStream并使用ReadLine()方法返回null?

4
在下面的代码中,我有一个StreamReader从网络流中读取。这段代码通常会运行良好几天。但是我遇到了一个问题,就是突然间StreamReader.ReadLine()开始返回null。
根据Microsoft文档,当StreamReader.ReadLine()达到输入流的末尾时,它将返回null。当底层流是NetworkStream时,这对我来说毫无意义。难道ReadLine()不应该一直阻塞,直到网络流接收到数据吗?
这是我第一次遇到这个问题,我还没有能够复制它。是什么导致了这个问题呢?
背景:应用程序从电话交换机接收CDR记录。电话交换机连接到应用程序并发送普通文本记录。在交换机连接后,除非出现故障,否则它将保持连接并继续发送记录。
    private void ProcessClient(TcpClient client)
    {
        try
        {
            using (NetworkStream stream = client.GetStream())
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    //continue processing while service is on
                    while (m_RunService & client.Connected)
                    {

                        string curLine = reader.ReadLine();

                        //code here does stuff to string
                        //will catch any exceptions that have to do with 
                        //processing the string
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //write to log
        }
    }

以下是启动监听器的代码:

    private void Listen()
    {
        try
        {
            while (m_RunService)
            {
                try
                {
                    m_TcpClient = m_TcpListener.AcceptTcpClient();

                    //run on same thread, should only ever be 1 cnx at a time
                    ProcessClient(m_TcpClient);
                }
                catch (Exception ex)
                {
                    //write to log
                }
                finally
                {
                    m_TcpClient.Close();
                }
            }
        }
        finally
        {
            m_TcpListener.Stop();
        }        
    } 

1
我刚刚编辑了我的帖子,当问题发生时,我的while <condition>检查了client.Connected。 - J Cooper
只想补充一点,虽然 Connected 可能会保持正确的值;但在你进行第一次调用之前,我不确定这个值有多可靠(因为它是在调用 ReadLine 之前被检查的)。 - bradenb
3个回答

5
< p > StreamReader 会一直阻塞直到收到数据 或者 连接被关闭。听起来似乎服务器发生了异常,关闭了连接,客户端没有收到数据。< /p >

我该如何检查这种情况? - J Cooper
@J Cooper:嗯,您是否总是期望在非错误情况下输出?如果是这样的话,那么您可以通过查看是否获得任何结果来检查它! - Jon Skeet

1
如果NetworkStream没有可用的数据,调用ReadLine()将返回null,因为它假定已经到达流的末尾。
在调用ReadLine之前,请尝试检查NetworkStream.CanReadNetworkStream.DataAvailable。如果连接未关闭,请手动阻塞一段时间,然后再次尝试读取。 编辑 您可以通过进行Send或使用底层的Socket来检查连接是否仍然打开:
Connected 属性获取 Socket 的连接状态,该状态是最后一次 I/O 操作的状态。当返回 false 时,Socket 要么从未连接过,要么不再连接。
Connected 属性的值反映了连接的状态,即最近操作的状态。如果您需要确定连接的当前状态,请进行非阻塞的零字节发送调用。如果调用成功返回或引发 WAEWOULDBLOCK 错误代码(10035),则表示套接字仍处于连接状态;否则,套接字不再连接。

当它按预期工作时,"that doesn't make sense" 没有意义。ReadLine() 会阻塞直到电话交换机发送另一条记录,这可能需要几分钟的时间。此时,ReadLine() 不会返回 null,而是一直阻塞。 - J Cooper
MSDN文档并没有明确说明ReadLine会阻塞,但它确实表示如果遇到IOExceptionOutOfMemoryException或到达输入流的末尾,它将返回。除此之外,我无法再添加更多信息了。这三种情况中的一种正在发生。 - bradenb
我觉得我开始理解了。所以基本上,如果我开始收到null,那么我应该运行一个检查来看是否可以发送消息。我的尝试接收消息(我的调用StreamReader.readline())不算是IO操作吗?(这应该会更新Connected属性) - J Cooper
我相信它是这样的,所以Connected应该可以工作,但我不能确定。 - bradenb

0

这听起来很像流已关闭。否则,它将会被阻塞。我的猜测是:网络出现问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接