c#Sokcet编程中的数据错误

时间:2017-06-05 10:52:24

标签: c# socket.io

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

当我尝试发送服务器鼠标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);
        }
    }

1 个答案:

答案 0 :(得分:0)

您似乎假设您的数据发送的相同单位到达;这可能适用于UDP,但是使用TCP流没有这样的保证 - 如果你启用了自动缓冲和/或“nagle”,它肯定不会发生。所以:当你从套接字获得“一些数据”时,message可以是(任何):

  • 正好一条消息
  • 一条消息的一半
  • 单个字符
  • 一条消息
  • 一条消息的结尾,17条完整的消息以及另一条消息的开头

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

  • 一个字符的结尾,一个完整字符和另一个字符的一半(零帧)

你的工作将TCP流分成“帧”(即流中的逻辑消息)。由于这是一个基于文本的协议,因此换行将是跟踪整个消息的明显方法。 你的工作是保留一个你无法处理的数据的后备缓冲区 - 即不完整的帧;应该(如上所述)是二进制,除非你知道你只会看到ASCII数据。