通过TCP实现显示屏截图请求及回传

Posted livelyleo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过TCP实现显示屏截图请求及回传相关的知识,希望对你有一定的参考价值。

在很多业务场景下,需要监视显示屏画面。在实时性要求不高的情况下,可以通过定时对显示屏进行截图及回传实现。

本文通过C#中提供的TCP通信功能,对该功能的实现进行简单描述。

首先,该功能的实现分为客户端和服务端。其中客户端发送显示屏截图请求;服务端接收截图请求后,进行截图并回传;客户端收到服务端回传的截图后,进行显示处理。

1. 客户端

    1)建立对目标主机的TCP连接

    2)向目标主机上的服务端发送截图指令

    3)接收目标主机上的服务端发回的内存流(代表截图),并解析为截图

    具体代码如下:

// 目标主机网络端点:hostIP表示目标主机IP,hostPort表示端口号
var hostEndPoint = new IPEndPoint(IPAddress.Parse(hostIP), hostPort);

// 连接目标主机的Socket
Socket clientSocket = null;
try
{
    // 创建Socket
    clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

    // 连接目标主机
    clientSocket.Connect(hostEndPoint);
}
catch (Exception ex)
{
    // 错误日志
}

// 建立Socket连接失败
if (clientSocket == null || !clientSocket.Connected)
return null;

// 向目标主机发送截图命令,截图命令为字符串常量"GetScreenSnap"
clientSocket.Send(Encoding.ASCII.GetBytes("GetScreenSnap"), "GetScreenSnap".Length, SocketFlags.None);

// 接收并解析截图
MemoryStream snapMemoryStream = null;
Image screenSnap = null;
try
{

    // 每次接收1024字节数据(服务端每次发送1024字节)
    byte[] by = new byte[1024];

    // 重试次数
    int retryCount = 0;

    // 前1024字节数据代表的字符串
    string s = "";
    while (true)
    {

        // 成功接收到前1024字节数据
        if ((clientSocket.Receive(by)) > 0)
        {

            // 转化为字符串
            s = Encoding.Unicode.GetString(by);
            by = new byte[1024];

            // 结束循环
            break;
        }

        // 接收失败后,重试次数加1
        retryCount++;

        // 重试次数超过5次
        if (retryCount > 5)
        {

            // 放弃接收截图
            break;
        }
    }

    // 前1024字节代表的字符串不为空
    if (!s.Equals(""))
    {

        // 解析出截图内存流的总字节长度
        s = s.Split(‘!‘)[0];
        long len = long.Parse(s);

        // 代表截图的内存流

        snapMemoryStream = new MemoryStream();

        // 依次接收字节流

        while (len > 0)
        {
            int number;
            if ((number = clientSocket.Receive(by)) > 0)
            {

               // 写入内存流
                snapMemoryStream.Write(by, 0, number);
                len -= number;
            }
            else
            {
                break;
            }
           by = new byte[1024];
        }

        // 根据内存流创建图片
        snapMemoryStream.Position = 0;
        screenSnap = Image.FromStream(snapMemoryStream);
     }
}
catch (Exception ex)
{
    // 错误日志
}
finally
{
    // 关闭内存流
    if (snapMemoryStream != null)
    snapMemoryStream.Close();

    // 关闭连接
    if (clientSocket != null)
    clientSocket.Close();

}

2. 服务端

    1)创建并启动TCP侦听器,监听客户端截图请求

    2)进行显示屏截图

    3)向客户端发送截图

    具体代码如下:

// 创建监听器并开始监听:localhostIP代表本机IP,port表示要监听的端口号
mSnapRequestListener = new TcpListener(localhostIP, port);
mSnapRequestListener.Start();

// 只要服务端在运行,则一直监听
while (isRunning)
{
    TcpClient tcpClient = null;
    Bitmap screenSnap = null;
    try
    {
        // 获取客户端发送的TcpClient
        tcpClient = mSnapRequestListener.AcceptTcpClient();
        if (tcpClient == null || tcpClient.Client == null)
        {
            return;
        }

        // 解析命令文本
        var inBuffer = new Byte["GetScreenSnap".Length];
        tcpClient.Client.Receive(inBuffer, "GetScreenSnap".Length, SocketFlags.None);
        var commandText = Encoding.ASCII.GetString(inBuffer);
        // 不是截图命令
        if (commandText != "GetScreenSnap")
            return;

// 创建一张空白图片
var primaryScreenSize = Screen.PrimaryScreen.Bounds.Size;
screenSnap = new Bitmap(primaryScreenSize.Width, primaryScreenSize.Height, PixelFormat.Format32bppArgb);
// 将屏幕复制到图片上
using (var grfx = Graphics.FromImage(screenSnap))
{
        grfx.CopyFromScreen(new Point(0, 0), new Point(0, 0), primaryScreenSize);
}

using (var snapStream = new MemoryStream())
{
    // 将屏幕截图保存入内存流,并将内存流位置设为0
    screenSnap.Save(snapStream, ImageFormat.Jpeg);
    snapStream.Position = 0;

    // 截图内存流长度
    var streamLength = snapStream.Length.ToString();
    // 扩充为512位(Unicode编码中为1024字节),右边以‘!‘填充
    streamLength = streamLength.PadRight(512, ‘!‘);

    // 初次发送截图内存流长度
    var snapBytes = Encoding.Unicode.GetBytes(streamLength);

    do
    {
        tcpClient.Client.Send(snapBytes);
    }
    // 从流中读取1024个字节,直到读完为止
    while (snapStream.Read(snapBytes, 0, 1024) > 0);
}

    }catch (Exception ex)
    {
        // 错误日志
    }
    finally
    {
        // 销毁图片
        if (screenSnap != null)
        {
            screenSnap.Dispose();
        }

        // 关闭连接
        if (tcpClient != null && tcpClient.Client != null && tcpClient.Client.Connected)
        {
            tcpClient.Client.Close();
        }
    }
}

 

以上是关于通过TCP实现显示屏截图请求及回传的主要内容,如果未能解决你的问题,请参考以下文章

python 读取图片成ndarray,resize,显示并回传

Layui的数据表格增删改,后端回传json格式封装

Golang TCP客户端实现菜单显示,实现广播聊天

Golang TCP客户端实现菜单显示,实现广播聊天

1200modbus连续读取多个数据

android中怎么实现客户端输入一条查询信息通过数据库返回并在客户端显示