Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 客户端/服务器TCP通信期间网络流脏_C#_Tcpclient - Fatal编程技术网

C# 客户端/服务器TCP通信期间网络流脏

C# 客户端/服务器TCP通信期间网络流脏,c#,tcpclient,C#,Tcpclient,我有一个客户端和一个服务器通过TCP进行通信。 客户端使用NetworkStream将信息发送到服务器,服务器将其读回,然后该过程将继续,直到用户想要退出并关闭连接。问题是网络流在前一次写入时变脏。因此,假设客户机在第一次发送字符串“aa”,在第二次发送字符串“b”。在第二次读取时,服务器将获得“ba”。这里少了什么?在服务器读取期间不应该使用NetworkStream吗?这是相关的代码 服务器 while (true) { try

我有一个客户端和一个服务器通过TCP进行通信。 客户端使用NetworkStream将信息发送到服务器,服务器将其读回,然后该过程将继续,直到用户想要退出并关闭连接。问题是网络流在前一次写入时变脏。因此,假设客户机在第一次发送字符串“aa”,在第二次发送字符串“b”。在第二次读取时,服务器将获得“ba”。这里少了什么?在服务器读取期间不应该使用NetworkStream吗?这是相关的代码

服务器

        while (true)
        {
            try
            {
                NetworkStream clientStream = tcpClient.GetStream();
                bytesRead = clientStream.Read(messageBytes, 0, messageBytes.Length);
            }
            catch (Exception ex)
            {
                LogToConsole(clientEndPoint, String.Format("[ERROR] Exception: {0}", ex.Message));
                break;
            }

            if (bytesRead == 0)
            {
                LogToConsole(clientEndPoint, "Client has disconnected");
                break;
            }

            messageCounter++;
            string message = Encoding.ASCII.GetString(messageBytes);
            message = message.Substring(0, message.IndexOf('\0'));
            LogToConsole(clientEndPoint, String.Format(" >> [{0}] Message received: {1}", messageCounter, message));
        }
客户

            string infoToSend = null;
            do
            {
                Console.Write(" >> Info to send: ");
                infoToSend = Console.ReadLine();

                if (!String.IsNullOrEmpty(infoToSend))
                {
                    NetworkStream serverStream = client.GetStream();
                    byte[] buffer = Encoding.ASCII.GetBytes(infoToSend);
                    serverStream.Write(buffer, 0, buffer.Length);
                    serverStream.Flush();
                }
            } while (!String.IsNullOrEmpty(infoToSend));
解决方案 正如Douglas所发现的,缓冲区(messageBytes)在以前的读取中是脏的。最后,我为服务器编写了以下代码(我发布了整个代码,因为它可能对其他人有用):

上面的调用每次都对整个缓冲区进行解码,尽管每条消息只会写入它的前n个字节(其中n是消息长度)。您的第一条消息“aa”被写入缓冲区的前两个字节。您的第二条消息“b”仅写入第一个字节,覆盖第一个“a”字符,但保留第二个“a”字符不变。这就是为什么在您的第二条消息之后,缓冲区似乎包含“ba”

您可以通过将上述调用更改为:

string message = Encoding.ASCII.GetString(messageBytes, 0, bytesRead);
但是,您的代码仍然会受到另一个问题的影响:
NetworkStream.Read
只读取当前可用的数据。如果客户端仍在传输,则可能会返回部分消息。因此,服务器可能会将这两条消息读取为“a”和“ab”

在您的情况下,由于您似乎只发送单行文本消息,因此可以将
NetworkStream
包装在服务器的
StreamReader
和客户端的
StreamWriter
中。然后,只需在服务器上调用
StreamReader.ReadLine
,在客户端调用
StreamWriter.WriteLine
ReadLine
将继续读取,直到遇到换行符,并在到达流末尾时返回
null

服务器:

using (NetworkStream clientStream = tcpClient.GetStream())
using (StreamReader reader = new StreamReader(clientStream))
{
    while (true)
    {
        message = reader.ReadLine();

        if (message == null)
        {
            LogToConsole(clientEndPoint, "Client has disconnected");
            break;
        }

        messageCounter++;
        LogToConsole(clientEndPoint, String.Format(" >> [{0}] Message received: {1}", messageCounter, message));
    }
}
客户:

using (NetworkStream serverStream = client.GetStream())
using (StreamWriter writer = new StreamWriter(serverStream))
{
    do
    {
        Console.Write(" >> Info to send: ");
        infoToSend = Console.ReadLine();

        if (!String.IsNullOrEmpty(infoToSend))
            writer.WriteLine(infoToSend);

    } while (!String.IsNullOrEmpty(infoToSend));
}

如果您的客户可以在您的邮件中发送换行符,则此解决方案将不起作用。

Aha。很好,你发现了。缓冲区确实是脏的。我将在原始问题中公布我最终实现的内容。谢谢
using (NetworkStream clientStream = tcpClient.GetStream())
using (StreamReader reader = new StreamReader(clientStream))
{
    while (true)
    {
        message = reader.ReadLine();

        if (message == null)
        {
            LogToConsole(clientEndPoint, "Client has disconnected");
            break;
        }

        messageCounter++;
        LogToConsole(clientEndPoint, String.Format(" >> [{0}] Message received: {1}", messageCounter, message));
    }
}
using (NetworkStream serverStream = client.GetStream())
using (StreamWriter writer = new StreamWriter(serverStream))
{
    do
    {
        Console.Write(" >> Info to send: ");
        infoToSend = Console.ReadLine();

        if (!String.IsNullOrEmpty(infoToSend))
            writer.WriteLine(infoToSend);

    } while (!String.IsNullOrEmpty(infoToSend));
}