尝试改进发送/接收 - 套接字的数据

时间:2018-02-04 13:02:37

标签: c# .net sockets

我正在尝试为C#.NET中的一个研究项目开发一个远程维护工具,它允许服务器和客户端之间的VoIP通信。此外,客户端必须将原始格式的屏幕截图数据发送到服务器,并显示在服务器上的PictureBox中。 (一开始我希望通过1 Gbit LAN每秒大约2个屏幕截图进行数据传输 - 这应该是小流量来处理)

我对Socket开发很新,并为 Chunk-size 我的数据创建了一些代码用于发送和接收。

在片刻,我的代码(或多或少)有效。图片显示在PictureBox中,我没有错误。但我知道 - 这是一种非常低效的方法。

我的问题是:当我只向服务器发送1个屏幕截图时,流量和工具的内存非常高(屏幕截图的平均大小约为350 kbyte)

我的下一个问题是:服务器不知道数据传输何时完成。他一直在监听数据,但我不知道如何从客户端发送命令来停止服务器监听并等待新的数据传输。

我的问题是:

  1. 你们能否给我一个如何提高我的代码性能的提示?也许我应该做整件事 async

  2. 如何在收到所有Chunk_Size数据时告诉服务器?

  3. 处理客户端 -Socket连接的常用方法是什么?我应该像在SQL中那样执行此操作:打开连接 - >发送/接收数据 - >关闭连接? 或者我应该创建一个Socket对象并让连接打开?

  4. 请查看我的代码

    客户端:

        //----- Test Send button -------- //
        public void button2_Click(object sender, EventArgs e)
        {
            const int CHUNK_SIZE = 8192;
            byte[] dataToSend = ScreenshotToByteArray();
            byte[] buff;
    
            int loop_length = (dataToSend.Length / CHUNK_SIZE) + 1;
            int modulo = dataToSend.Length % CHUNK_SIZE;
            int offset = 0, i = 0;
    
            while (i <= loop_length)
            {
                ++i;
    
                if (i == loop_length) // check for the last piece
                {
                    if (modulo != 0)
                    {
                        buff = new byte[modulo];
                        Buffer.BlockCopy(dataToSend, dataToSend.Length - modulo, buff, 0, modulo);
                        clientSocket.Send(buff, 0, buff.Length, SocketFlags.None);
                        break; 
                    }
                    else
                    {
                        break;
                    }
                }
                else // this part is the main chunk piece
                {
                    buff = new byte[CHUNK_SIZE];
                    Buffer.BlockCopy(dataToSend, offset, buff, 0, CHUNK_SIZE);
                    clientSocket.Send(buff, 0, buff.Length, SocketFlags.None);
                    offset += CHUNK_SIZE;
                }
            }
        }
    
    
        //------- ScreenImage To Byte Array ------ //
        private static byte[] ScreenshotToByteArray()
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;
            using (Bitmap bmp = new Bitmap(screenWidth, screenHeight))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, bmp.Size);
                    ImageConverter converter = new ImageConverter();
                    return (byte[])converter.ConvertTo(bmp, typeof(byte[]));
                }
            }
        }
    

    服务器

        MemoryStream mStream = new MemoryStream();
    
        // ---------- Receive Callback --------------//
        private void ReceiveCallback()
        {
            try 
            {
                byte[] buff = new byte[8192];
                int received;
                while((received = ClientSocket.Receive( buff,0, buff.Length, SocketFlags.None )) > 0) 
                {
                    mStream.Write( buff, 0, received );
                }
            } 
            catch (SocketException ex)
            {
                this.ShowErrorDialog( ex.Message );
            }
            catch (ObjectDisposedException ex)
            {
                this.ShowErrorDialog( ex.Message );
            } 
        }
    
        // ------------- Button to show Image ------ //
        private void button2_Click( object sender, EventArgs e )
        {
            if (mStream.Length > 0) 
            {
                this.pictureBox.Image = ConvertByteArrayToImage(mStream.ToArray() );
            }
        }
    

1 个答案:

答案 0 :(得分:0)

  1. 任何与流或IO相关的内容都可以更好地执行Async
  2. 您可以先发送要接收的字节数,以便服务器事先知道何时停止收听
  3. 创建连接是一个应该省略的负载。像SQL这样的连接池机制更可取。
  4. 可能是发送大量图像的最后一个提示;

    1. 将您的位图压缩为PNG或JPEG
    2. 也许从TCP切换到UDP连接。如果发送数据是每秒2个图像,那么最好保持正常运行,如果消息失败,那么只需获取下一个图像