TcpClient未收到完整的服务器应答

本文关键字:服务器 应答 TcpClient | 更新日期: 2023-09-27 17:51:16

下面的方法应该向服务器发送两个命令。它还应该以字符串的形式从服务器返回完整的应答。我的问题是与代码的回复部分;具体来说,我没有得到完整的回复。如果我在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 "";
    }

TcpClient未收到完整的服务器应答

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

添加console时。Readline,你给网络数据包一个机会来赶上,并在缓冲区中获得更多的数据。

相反,你应该一直循环,直到网络流关闭,或者因为它是一个tcp流,无论你使用什么协议,它都会告诉你你的应用程序数据包有多大,

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

尝试在循环后将所有写操作刷新到流:

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