在不少業務場景下,須要監視顯示屏畫面。在實時性要求不高的狀況下,能夠經過定時對顯示屏進行截圖及回傳實現。網絡
本文經過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(); } } }