局域网控制(一)界面传输

来源:互联网 发布:赋码软件 编辑:程序博客网 时间:2024/06/11 07:34

 突然想起来用API结合C#的网络编程来做点东西!

    结合Socket通信及Windows API,通过发送或接收数据来执行相应的操作,可以实现对某台计算机操作。下面就一个简单的局域网控制实例来说明这一过程,具体可以通过一个客户端和一个控制端来实现,客户端主要运行在客户计算机上(即被控制的计算机上),控制端运行在服务器主机上。

无论是对于客户端还是控制端,都必须包含发送数据至目标计算机上和接受目标计算机上的数据这两部分,这个过程主要通过Socket通信来实现。至于具体发送什么数据以及如何将这些数据来转换成计算机指令,则主要是API的事情了。

首先新建一个客户端项目,其界面上主要的控件及控件名称如下图所示:

图片

然后新建一个控制端项目,其界面上主要的控件及控件名称如下图所示:


图片

1、界面传输

首先来实现将客户端的界面传送至控制端,这个过程主要包括两个部分:在客户端传输本机界面至控制端、在控制端接受传输的数据。具体来说,在客户端传输本机界面至控制端又分为获取界面图像、将图形转换成传输数据(如字节)、传输数据。同样,在控制端接受传输的数据在接受数据流后,将数据流转换成字节后还需要转换成图形。下面来分别介绍这五个关键点如何来实现:

1)获取界面图像

获取界面图像主要通过BitBlt()CreateDC()来实现,首先必须对这两个函数进行引用,如下:

【客户端】:

 [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]

        private static extern bool BitBlt(

         IntPtr hdcDest, //目标设备的句柄

         int nXDest, // 目标对象的左上角的X坐标

         int nYDest, // 目标对象的左上角的Y坐标

         int nWidth, // 目标对象的矩形的宽度

         int nHeight, // 目标对象的矩形的长度

         IntPtr hdcSrc, // 源设备的句柄

         int nXSrc, // 源对象的左上角的X坐标

         int nYSrc, // 源对象的左上角的X坐标

         System.Int32 dwRop // 光栅的操作值

         );

        [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]

        private static extern IntPtr CreateDC(

         string lpszDriver, // 驱动名称

         string lpszDevice, // 设备名称

         string lpszOutput, // 无用,可以设定位"NULL"

         IntPtr lpInitData // 任意的打印机数据

         );

然后定义一个获取屏幕的函数GetScreenImage(),其返回值为Bitmap,该函数代码如下:

【客户端】:

        private Bitmap GetScreenImage(Point point01, Point point02, bool full)

        {

            //创建显示器的DC

            IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);

            //由一个指定设备的句柄创建一个新的Graphics对象

            Graphics g1 = Graphics.FromHdc(dc1);

            Bitmap MyImage;

            int width, height;

            if (full)

            {

                width = Screen.PrimaryScreen.Bounds.Width;

                height = Screen.PrimaryScreen.Bounds.Height;

            }

            else

            {

                width = point02.X - point01.X;

                height = point02.Y - point01.Y;

            }

 

            //根据指定的宽度和高度创建一个与之相同大小的Bitmap对象

            MyImage = new Bitmap(width, height, g1);

 

            //获得屏幕的句柄

            Graphics g2 = Graphics.FromImage(MyImage);

            //获得位图的句柄

            IntPtr dc3 = g1.GetHdc();

            //把当前屏幕捕获到位图对象中

            IntPtr dc2 = g2.GetHdc();

            //把当前屏幕拷贝到位图中

            BitBlt(dc2, 0, 0, width, height, dc3, point01.X, point01.Y, 13369376);

            //释放屏幕句柄

            g1.ReleaseHdc(dc3);

            //释放位图句柄

            g2.ReleaseHdc(dc2);

            return MyImage;

        }

2)转换图像至字节

转换图像为字节可以采用MemoryStream类来实现,通过该类将图像读入内存流中,然后使用该类的ToArray()方法将数据流转换成字节数组,如下代码:

                Point point01 = new Point(), point02 = new Point();

                Bitmap bitmap = GetScreenImage(point01, point02, true);               

                MemoryStream memoryStream = new MemoryStream();                bitmap.Save(memoryStream,System.Drawing.Imaging.ImageFormat.Bmp);

                byte[] bytes = memoryStream.ToArray();

3)发送字节至控制端

发送数据主要还是采用TcpClient类来实现,通过TcpClient类连接控制端,如果连接成功则将图像转换成字节数据,并发送出去。如下代码:

【客户端】:

        private void SendImage()

        {

            TcpClient client = new TcpClient();

            Int32 port = Int32.Parse(portTextBox.Text);

            client.Connect(IPAddress.Parse(IPAddressTextBox.Text), port);

            if (client.Connected)

            {

                Point point01 = new Point(), point02 = new Point();

                Bitmap bitmap = GetScreenImage(point01, point02, true);               

                MemoryStream memoryStream = new MemoryStream();

                bitmap.Save(memoryStream,System.Drawing.Imaging.ImageFormat.Bmp);

                byte[] bytes = memoryStream.ToArray();

                NetworkStream stream = client.GetStream();

                stream.Write(bytes, 0, bytes.Length);

                stream.Close();

                client.Close();

            }

        }

在需要发送本机界面至控制端上,只需要调用SendImage()函数即可。

4将字节转换成图形

这个过程是在控制端获得客户端发送的数据后,通过接收的数据转换成图形。同样是采用MemoryStream类将字节数组读入内存流,然后使用Image类的FromStream()方法将数据流转换成图像,如下代码:

                        MemoryStream memoryStream = new MemoryStream();

                        byte[] bytes = new byte[1024];

                        int i;

                        while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)

                        {

                            memoryStream.Write(bytes, 0, i);

                        }

                        Image image = Image.FromStream(memoryStream);

其中,stream是获取的网络数据流,即接收的客户端传输的数据。

5)控制端接收数据

在控制端接收数据仍然采用TcpListener类来监听客户端发送的数据,如果有数据传输过来,就将其转换成图像。所以首先要在全局中定义TcpListener类,如下:

【控制端】:

TcpListener tcpListener;

然后定义监听函数用于监听客户端发送的数据,如下:

【控制端】:

        private void Listen()

        {

            try

            {

                Int32 port = Int32.Parse(portTextBox.Text);

                tcpListener = new TcpListener(port);

                tcpListener.Start();

                while (true)

                {

                    TcpClient client = tcpListener.AcceptTcpClient();

                    NetworkStream stream = client.GetStream();

                    if (stream.CanRead)

                    {

                        System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

                        MemoryStream memoryStream = new MemoryStream();

                        byte[] bytes = new byte[1024];

                        int i;

                        while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)

                        {

                            memoryStream.Write(bytes, 0, i);

                        }

                        Image image = Image.FromStream(memoryStream);

                        ClientPictureBox.Image= image;

                        memoryStream.Close(); 

                    }

                    client.Close();

                }

            }

            finally

            {

                tcpListener.Stop();

            }

        }

在控制端用一个PictureBox控件(设置其Name属性为ClientPictureBox)来显示从客户端返回的界面,运行程序,其结果如下图所示:

图片

原创粉丝点击