代码之家  ›  专栏  ›  技术社区  ›  Emcrank

为什么这两个StreamWriter构造函数给了我不同的结果?

  •  0
  • Emcrank  · 技术社区  · 7 年前

    长话短说,我正在尝试使用StreamWriter通过TcpClient发送字符串。

    除了交换这些示例外,不更改任何其他代码。它们产生不同的结果。

    在代码示例1中 StreamReader检测到它有可用的数据,并接收到消息。

    在代码示例2中

    示例1-写入方法

        public void SendMessage(string message)
        {
            message = "TestMessage";
    
            //WORKING - Sample 1
            using (var sw = new StreamWriter(stream))
            {
                sw.Write(message);
                sw.Flush();
            }
        }
    

    示例2-写入方法

        public void SendMessage(string message)
        {
            message = "TestMessage";
    
            //NOT WORKING - Sample 2
            var encoding = new UTF8Encoding(false, true);
            using (var sw = new StreamWriter(stream, encoding, 1024, true))
            {
                sw.Write(message);
                sw.Flush();
            }
        }
    

    读取方法

        public string ReadMessage()
        {
            if (!stream.DataAvailable)
                return null;
    
            //I have also tried
            //if(sr.Peek() == 0)
            //  return null;
    
            string message = sr.ReadToEnd();
            return message;
        }
    

    注释 :如果我最后将两个示例与工作示例放在一起,我会收到消息“TestMessageTestMessage”,因此它肯定正在写入流,但它没有将DataAvailable设置为true?

    知道为什么吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   user8259632 user8259632    7 年前

    问题是你的 ReadToEnd() 在上无限阻塞的命令 NetworkStream 直到关闭才有尽头。我测试了你的代码,通过了 DataAvailable 在上查询并阻止 ReadToEnd() 命令

    BaseStream 保持开放意味着你永远不会有终点。当工作方法关闭流时 ReadMessage 方法返回流中的所有内容。

    解决方法:不要试图读到最后。在数据可用时读入块,或引入终止字符并读入该字符。

    从…起 MSDN:

    ReadToEnd假设流知道何时结束。对于交互式协议,服务器仅在您请求数据时发送数据,并且不关闭连接,ReadToEnd可能会无限期阻塞,因为它没有到达终点,因此应该避免。