2017-06-05 48 views
0

我一直在开发简单的远程桌面程序发送,接收服务器,客户端之间的屏幕图像和做鼠标控制,键盘控制。c#Sokcet编程错误的数据

当我试图发送服务器鼠标X,Y位置到客户端进行控制时,客户端收到错误的数据。

ex)服务器发送的数据是MouseControl$Position$10(Mouse_X_Position)$10(Mouse_Y_Position)$450(pictureBox.Width)$450(pictureBox.Height)。它首先运行良好,客户端收到服务器发送的相同数据。但是,几秒钟后客户端收到像ntrol$Position$10(Mouse_X_Position)$10(Mouse_Y_Position)$450(pictureBox.Width)$450(pictureBox.Height)这样的数据。第一个字MouseControl的某些部分在服务器仍然发送正确数据时消失MouseControl$Position$10(Mouse_X_Position)$10(Mouse_Y_Position)$450(pictureBox.Width)$450(pictureBox.Height)

帮助我摆脱这种麻烦。我想知道它为什么会发生 提前谢谢!

这里是低于

-server 
    private void StartMouseControl() 
    { 
     NetworkStream MouseControlStream = MouseControlDataSock.GetStream(); 
     byte[] buffer = null; 

     while (true) 
     { 
      Point PointXY = pictureBox1.PointToClient(new Point(Control.MousePosition.X, Control.MousePosition.Y)); 
      int MouseX = PointXY.X; 
      int MouseY = PointXY.Y; 

      /* when mouse pointer in pictureBox ... */ 
      if ((MouseX >= 0 && MouseX <= pictureBox1.Width) && (MouseY >= 0 && MouseY <= pictureBox1.Height)) 
      { 
       MouseControlStream.Flush(); 
       buffer = Encoding.Unicode.GetBytes("MouseControl$Postion$" + MouseX.ToString() + "$" + MouseY.ToString() + "$" + pictureBox1.Width.ToString() + "$" + pictureBox1.Height.ToString()); 
       MouseControlStream.Write(buffer, 0, buffer.Length); 
       MouseControlStream.Flush(); 
      } 

      Thread.Sleep(400); 
     } 
    } 




    -client 
    private void StartMouseControl() 
    { 
     int BUFFERSIZE = 72; 
     int read; 
     byte[] buffer = new byte[BUFFERSIZE]; 

     while (MouseControlDataSock.Connected) 
     { 
      /* seperate protocol data from server and save in Sep_message[] */ 
      MouseControlstream = MouseControlDataSock.GetStream(); 

      read = 0; 
      while (read < buffer.Length) 
      { 
       int readbyte = MouseControlstream.Read(buffer, read, buffer.Length - read); 
       if (readbyte == 0) 
       { 
        break; 
       } 
       read += readbyte; 
      } 
      MouseControlstream.Flush(); 

      string message = Encoding.Unicode.GetString(buffer, 0, read); 

      string splitter = "$"; 
      char[] split = splitter.ToArray(); 

      string[] Sep_message = message.Split(split, StringSplitOptions.RemoveEmptyEntries); 

      if (Sep_message[0].Equals("MouseControl")) 
      { 
       if (Sep_message[1].Equals("Postion")) 
       { 
        // Mouse_X_Position, Mouse_Y_Position, pictureBox.Width, pictureBox.Height 
        int MouseX_FromServer = int.Parse(Sep_message[2]); 
        int MouseY_FromServer = int.Parse(Sep_message[3]); 
        int PicBoxWidth_FromServer = int.Parse(Sep_message[4]); 
        int PicBoxHeight_FromServer = int.Parse(Sep_message[5]); 
       } 
      } 

      Thread.Sleep(100); 
     } 
    } 
+0

谢谢你,Pikoh! –

回答

0

我的代码,你似乎是假设你的数据到达在它是发送相同的单位;这可能与UDP协同工作,但是对于TCP流而言,并不存在这样的保证 - 如果您启用了自动缓冲和/或“nagle”,那肯定不会发生。所以:当您从插座有“一些数据”,message可能是(任何):

  • 正好一个消息
  • 一半一条消息
  • 单个字符
  • 一个还有一点点消息
  • 一个消息,17个整个消息,和另一个

以Unicode的情况下开始的端部,它也可能是部分单个字符 - 这就是为什么你应该以二进制工作,直到你知道你有一个“框架”,并且只在框架内进行unicode解码。所以,你还需要考虑:

  • 一个字符,一个完整的角色,与其他角色的一半(零帧)

这是结束你的工作分割TCP流到“帧”(即流内的逻辑消息)。由于这是一个基于文本的协议,换行符将是跟踪整个消息的明显方式。这是您的工作,以保持您无法处理的数据的后台缓冲区 - 即不完整的帧;这应该(如提到)是二进制,除非你知道你只会看到ASCII数据。

+0

谢谢Marc Gravell!正如你所提到的那样,我将制作逻辑消息并将它们发送到服务器并进行分割,组合完整的帧。 –