【问题标题】:Inaccurate received message in the server服务器接收到的消息不准确
【发布时间】:2015-09-26 10:49:28
【问题描述】:

我在客户端-服务器中接收消息时遇到问题。我已经为测试设置了一个默认字符串。它可以很好地接收消息,但是在发送第二个循环时会将字符串粘在一起。我该怎么办?

这里是代码 发送数据(客户端)

NetworkStream networkStream = tcpclnt.GetStream();
String data = "";
     for (int i = 0; i < 4; i++)
         {
           data = " output here";
           if (networkStream.CanWrite)
              {
                var bytes = Encoding.ASCII.GetBytes(data);
                networkStream.Write(bytes, 0, bytes.Length);
                networkStream.Flush();
              }
          }

当它接收到数据时(服务器)

private void recieveData()
{
  NetworkStream nStream = tcpClient.GetStream();
  while (!stopReceiving)
      {
         if (nStream.CanRead)
           {
              byte[] buffer = new byte[1024];
              var bytesRead = nStream.Read(buffer, 0, buffer.Length);
              if (bytesRead > 0) recvDt = Encoding.ASCII.GetString(buffer, 0, bytesRead);
              bool f = false;
              f = recvDt.Contains("+@@+");
                    if (f)
                    {
                        string d = "+@@+";
                        recvDt = recvDt.TrimStart(d.ToCharArray());
                        clientDis();
                        stopReceiving = true;
                    }


                    else 
                    {
                        this.Invoke(new rcvData(addHere));
                    }
                }
                Thread.Sleep(1000);
            }

        }


public void addHere() 
        {
            if (recvDt != null && recvDt != "")
            {
                output.Text += "Received Data: " + recvDt;
                recvDt = null;
            }

        }

输出如下所示

【问题讨论】:

  • 我没有查看您的所有代码,但recvDt.Contains("+@@+") 会在某个时候中断。一个Send()不等于一个Receive(),数据可以部分发送和接收,导致你在一个Receive()收到“+@”,在下一个收到“@+”。您需要一个适当的应用程序/框架协议。
  • 我尝试删除该部分并留下“this.Invoke(new rcvData(addHere));” ..它仍然有相同的结果

标签: c# winforms client-server networkstream


【解决方案1】:

您假设 TCP 会保留您的消息。它不是。 TCP 提供无边界的字节流。您可以接收任何块大小的字节,包括一个,但也可以一次接收所有字节。

您需要设计一个应用程序协议,允许您将消息与字节流区分开来。也许,在消息前面加上它的长度。

或者,逐行发送并使用 StreamReader.ReadLine。它会为您处理。

这是一个错误:

                    string d = "+@@+";
                    recvDt = recvDt.TrimStart(d.ToCharArray());

您基本上是在修剪掉所有字符“+@”。不是你想要的。

为什么要测试CanReadCanWrite?众所周知,它们是真实的,即使它们是错误的,您的程序也会忽略问题并继续无所事事。如果您无论如何都无法处理结果,请不要进行这种迷信检查。

您可能根本不应该使用 TCP。这个很难(硬。使用更高级别的技术,例如 WCF、HTTP、protobuf。

【讨论】:

  • 您不厌倦每天发布此回复吗? ;-) 我曾经尝试写过canonical Q&A,但我认为它太复杂了,并没有真正说明正确实施自己的协议是困难且不必要的。
  • @CodeCaster 这证明了我现在有多无聊 :) 我想我现在应该开始工作了...
  • 但是消息在这里通过“this.Invoke(new rcvData(addHere));”因为它不符合 if.. 中的验证,并且当接收到“+@@+”时客户端断开连接
  • 不确定你的意思。 f 为 false 导致调用 addHere。打印到屏幕上。这有什么好惊讶的?另请注意,recvDt 可能会保留其旧值。这是另一个错误。
  • 我尝试删除该部分并保留 this.Invoke(new rcvData(addHere)); ...它仍然有相同的结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多