經過TCP實現顯示屏截圖請求及回傳

在不少業務場景下,須要監視顯示屏畫面。在實時性要求不高的狀況下,能夠經過定時對顯示屏進行截圖及回傳實現。網絡

本文經過C#中提供的TCP通訊功能,對該功能的實現進行簡單描述。tcp

首先,該功能的實現分爲客戶端和服務端。其中客戶端發送顯示屏截圖請求;服務端接收截圖請求後,進行截圖並回傳;客戶端收到服務端回傳的截圖後,進行顯示處理。編碼

1. 客戶端spa

    1)創建對目標主機的TCP鏈接日誌

    2)向目標主機上的服務端發送截圖指令code

    3)接收目標主機上的服務端發回的內存流(表明截圖),並解析爲截圖orm

    具體代碼以下:圖片

// 目標主機網絡端點: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();        }    } }

相關文章
相關標籤/搜索