【问题标题】:TcpClient not receiving full server replyTcpClient 没有收到完整的服务器回复
【发布时间】:2014-03-21 05:38:10
【问题描述】:

以下方法应该向服务器发送几个命令。它还应该以字符串形式从服务器返回完整回复。我遇到的问题是代码的回复部分;具体来说,我没有得到完整的回复。如果我在memoryStream.Write(buffer,0,bytesRead); 之前添加以下行Console.WriteLine(bytesRead);,我会收到完整的回复。似乎这行愚蠢的代码有助于“暂停”某些东西,以便返回所有数据。我真的不知道我做错了什么,我需要你的帮助。谢谢

    public string Send(List<string> commands)
    {
        try
        {
            // String that will contain full reply from server
            string fullServerReply = string.Empty;

            TcpClient tcpClient = new TcpClient(host, port);

            NetworkStream networkStream = tcpClient.GetStream();

            foreach (string command in commands)
            {
                // Check to see if this NetworkStream is writable
                if (networkStream.CanWrite)
                {
                    // Translate the passed message into UTF8 and store it as a byte array.
                    byte[] sendBytes = Encoding.UTF8.GetBytes(command);

                    // Send the message to the connected TcpServer.
                    networkStream.Write(sendBytes, 0, sendBytes.Length);
                }
                else
                {
                    // Close everything.
                    networkStream.Close();
                    tcpClient.Close();

                    return "";
                }

                // Check to see if this NetworkStream is readable
                if (networkStream.CanRead)
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        // Buffer to store the response bytes.
                        byte[] buffer = new byte[1024];

                        do
                        {
                            int bytesRead = networkStream.Read(buffer, 0, buffer.Length);

                            if (bytesRead <= 0)
                            {
                                break;
                            }

                            //Console.WriteLine(bytesRead); <- BY ADDING THIS CODE I GET THE FULL REPLY

                            memoryStream.Write(buffer, 0, bytesRead);

                        } while (networkStream.DataAvailable);

                        memoryStream.Position = 0;
                        fullServerReply += Encoding.UTF8.GetString(memoryStream.ToArray()); // THIS STRING DOES NOT CONTAIN FULL REPLY
                    }
                }
                else
                {
                    // Close everything.
                    networkStream.Close();
                    tcpClient.Close();

                    return "";
                }
            }

            // Close everything.
            networkStream.Close();
            tcpClient.Close();

            return fullServerReply.Trim();
        }
        catch (ArgumentNullException ex)
        {
            return "";
        }
        catch (SocketException ex)
        {
            return "";
        }

        return "";
    }

【问题讨论】:

    标签: c# tcpclient memorystream networkstream


    【解决方案1】:

    是的! DataAvailable 不表示已收到完整的流。它仅指示接收缓冲区中是否有一些尚未准备好的数据可用。

    添加 console.readline 后,网络数据包就有机会赶上并在缓冲区中获取更多数据。

    相反,您应该继续循环,直到网络流关闭,或者因为它是一个 tcp 流,无论您使用的协议告诉您应用程序数据包有多大,都需要继续读取。

    【讨论】:

    • 您能否举个例子说明我如何检查网络流是否已关闭?服务器使用的协议并没有告诉我数据包的大小。
    • 那么“协议”基本上是发送请求并继续读取所有内容,直到对等方关闭套接字?
    • @jadrijan 我相信this SO thread 中的答案使用了适当的技术,尽管我只是在对其进行了相当粗略的检查后才这么说 - 用一粒盐(和一些胡椒粉)来接受这个建议:)。
    【解决方案2】:

    这就是网络的工作原理——您不能假设您可以立即恢复所有内容,或者读取次数与写入次数相同。在您的情况下,将写入添加到控制台足以让客户端假脱机所有内容。

    【讨论】:

      【解决方案3】:

      尝试在循环后刷新所有写入流:

      memoryStream.Flush();
      memoryStream.Position = 0;
      fullServerReply += Encoding.UTF8.GetString(memoryStream.ToArray()); // THIS STRING DOES NOT CONTAIN FULL REPLY
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-19
        • 2017-09-01
        • 1970-01-01
        • 2016-07-25
        • 1970-01-01
        • 2021-10-31
        • 1970-01-01
        相关资源
        最近更新 更多