最新基于Qt实现多电脑屏幕监控

本项目的原理是,多客户端通过后台的不断截屏,通过TCP socket 发送到服务器端进行项目,目前我代码里面设置最大监控4台电脑,当然你也可以自己设置哈。

客户端代码

//头文件tcpimageclient.h

#ifndef TCPIMAGECLIENT_H
#define TCPIMAGECLIENT_H
#include<QObject>
#include<QTcpSocket>
#include<QTimer>

class TcpImageClient:public QObject
{
    Q_OBJECT
public:
    TcpImageClient(QString ipAddr,QObject* parent=0);
    ~TcpImageClient();
    void sendImageData(QByteArray imageData);
public:signals:
    void connectSuccess();
    void distConnect();
private slots:
    void connectHost();
private:
    QTcpSocket *m_socket;
    QString _ipAddress;

    QTimer* time;
};

#endif // TCPIMAGECLIENT_H


//tcpimageclient.cpp 


#include"tcpimageclient.h"
#include<QDebug>

TcpImageClient::TcpImageClient(QString ipAddr,QObject *parent):QObject(parent)
{
    _ipAddress = ipAddr;
    m_socket = new QTcpSocket(this);
    time = new QTimer(this);
    m_socket->abort();
    connect(m_socket,SIGNAL(connected()),time,SLOT(stop()));
    connect(m_socket,SIGNAL(connected()),this,SIGNAL(connectSuccess()));
    connect(m_socket,SIGNAL(disconnected()),this,SIGNAL(distConnect()));
    connect(time,SIGNAL(timeout()),this,SLOT(connectHost()));
    time->start(200);
}

TcpImageClient::~TcpImageClient()
{

}

void TcpImageClient::sendImageData(QByteArray imageData)
{
//    qDebug()<<imageData.size();
    m_socket->write(imageData);

}

void TcpImageClient::connectHost()
{
    if(m_socket->state() == QAbstractSocket::ConnectingState)
        return;
    m_socket->connectToHost(_ipAddress,19999);
}

//实现很简单,就没有什么注释了

//desktopclient.h

#ifndef DESKTOPCLIENT_H
#define DESKTOPCLIENT_H

#include <QWidget>
#include<QPixmap>
#include"tcpimageclient.h"
#include<QScreen>
#include<QTimer>
#include<QSystemTrayIcon>
#include<QMenu>
#include<QAction>

namespace Ui {
class DeskTopClient;
}

class DeskTopClient : public QWidget
{
    Q_OBJECT

public:
    explicit DeskTopClient(QWidget *parent = 0);
    ~DeskTopClient();

private slots:
    void SendCutImageData();
    void HandleClose();
private:
    Ui::DeskTopClient *ui;
    TcpImageClient *m_client;
    QScreen *screen;
    QTimer * time;

    QSystemTrayIcon *m_trayIcon;
    QMenu *mMenu;
    QAction *exitAction;
    QString _ipAddr;
    int _machineId;
    int _frame;

    void ReadConfig();

};

#endif // DESKTOPCLIENT_H

//desktopclient.cpp

#include "desktopclient.h"
#include "ui_desktopclient.h"
#include<QMessageBox>
#include<QPixmap>
#include<QDebug>
#include<QBuffer>
#include<QDataStream>
#include<QByteArray>
#include<QIODevice>
#include<QSettings>

DeskTopClient::DeskTopClient(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DeskTopClient)
{
    ui->setupUi(this);

    this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::ToolTip);
    m_trayIcon = new QSystemTrayIcon(this);
    m_trayIcon->setIcon(QIcon(":/view.ico"));     //设置图标
    mMenu = new QMenu(this);
    exitAction = new QAction(QStringLiteral("Exit"),this);
    mMenu->addAction(exitAction);
    m_trayIcon->setContextMenu(mMenu);
    connect(exitAction,SIGNAL(triggered(bool)),this,SLOT(HandleClose()));
    m_trayIcon->show();
    m_trayIcon->showMessage("tip","desktopclient has started",QSystemTrayIcon::Information,1000);
    ReadConfig();


    screen = QGuiApplication::primaryScreen();
    m_client = new TcpImageClient(_ipAddr);
    time = new QTimer(this);
    time->setInterval(1000/_frame);
    connect(time,SIGNAL(timeout()),this,SLOT(SendCutImageData()));
    connect(m_client,SIGNAL(connectSuccess()),time,SLOT(start()));
    connect(m_client,SIGNAL(distConnect()),time,SLOT(stop()));
}

DeskTopClient::~DeskTopClient()
{
    delete m_client;
    delete ui;
}


void DeskTopClient::SendCutImageData()
{
    QPixmap image =  screen->grabWindow(0);//抓屏
    QBuffer buffer;
    image.save(&buffer,"PNG");
    quint32 len = buffer.data().size() + 8;//设置发送数据的长度
    QByteArray dataArray;
    QDataStream stream(&dataArray,QIODevice::WriteOnly);
    stream << len;//数据长度
    stream << _machineId;//电脑ID
    dataArray.append(buffer.data());
    m_client->sendImageData(dataArray);

}

void DeskTopClient::HandleClose()
{
    QApplication::quit();
}

void DeskTopClient::ReadConfig()
{
      QSettings settings("config.ini",QSettings::IniFormat);
      settings.beginGroup("config");
      if(settings.value("ipAddr").toString().isEmpty()){
          QMessageBox box;
          box.setWindowTitle("ip地址错误");
          box.setText("请先配置服务端IP地址,再打开");
          box.exec();
          HandleClose();
          return;
      }
      _ipAddr = settings.value("ipAddr").toString();

      if(settings.value("machineId").toString().isEmpty()){
          QMessageBox box;
          box.setWindowTitle("ip地址错误");
          box.setText("请先配置机器ID,再打开");
          box.exec();
          HandleClose();
          return;
      }
      _machineId = settings.value("machineId").toInt();


      if(settings.value("frame").toString().isEmpty()){
          QMessageBox box;
          box.setWindowTitle("ip地址错误");
          box.setText("请先配置帧率,再打开");
          box.exec();
          HandleClose();
          return;
      }

      _frame = settings.value("frame").toInt();
      settings.endGroup();

}

服务端

//tcpimageserver.h



#ifndef TCPIMAGESERVER_H
#define TCPIMAGESERVER_H
#include<QTcpServer>
#include<QTcpSocket>
#include<QObject>
#include<QMap>

class TcpImageServer:public QObject
{
    Q_OBJECT
public:
    TcpImageServer(QObject* parent=0);
    ~TcpImageServer();
public:signals:
    void recvImage(QByteArray imageData,int index);

private slots:
    void newConnect();
    void readMessage();
    void removeClient();
private:
    QTcpServer *m_server;
    QMap<QString,QTcpSocket*>m_mapClient;
    QMap<QTcpSocket*,QByteArray>m_recvData;

    void xmlData();
};


#endif // TCPIMAGESERVER_H


//tcpimageserver.cpp



#include"tcpimageserver.h"
#include<QHostAddress>
#include<QDataStream>
#include<QBuffer>
#include<QDebug>

TcpImageServer::TcpImageServer(QObject* parent):QObject(parent)
{
    m_server = new QTcpServer(this);
    m_server->setMaxPendingConnections(4);//这里是我设置最大接入数是4
    m_server->listen(QHostAddress::Any,19999);
    connect(m_server,SIGNAL(newConnection()),this,SLOT(newConnect()));
}

TcpImageServer::~TcpImageServer()
{

}

void TcpImageServer::newConnect()
{
    QTcpSocket * m_socket = m_server->nextPendingConnection();
    connect(m_socket,SIGNAL(readyRead()),this,SLOT(readMessage()));
    m_mapClient.insert(m_socket->peerAddress().toString(),m_socket);
    connect(m_socket,SIGNAL(disconnected()),this,SLOT(removeClient()));


}

void TcpImageServer::readMessage()
{
    QTcpSocket *m_socket = reinterpret_cast<QTcpSocket*>(sender());
    QByteArray dataArray =  m_socket->readAll();
    if(m_recvData.contains(m_socket))
        m_recvData[m_socket].append(dataArray);   //由于图片数据过大,会存在多包发送,因此先用容器存储在解析
    else
        m_recvData[m_socket] = dataArray;
    xmlData();
}

void TcpImageServer::xmlData()//解析一张图片数据
{
     QMap<QTcpSocket*,QByteArray>::iterator it;

    for(it = m_recvData.begin();it!=m_recvData.end();it++)
    {
        if(it.value().size() == 0)
            continue;

        int size = 0;
        int machineId = 1;
        QDataStream stream(& it.value(),QIODevice::ReadOnly);
        stream >> size;
        stream >> machineId;
        if(size <= it.value().size()){
            QByteArray imageData = it.value().mid(8,size);
            it.value() = it.value().mid(size);
            emit recvImage(imageData,machineId);
        }

    }
}

void TcpImageServer::removeClient()
{
     QTcpSocket* socket = reinterpret_cast<QTcpSocket*>(sender());

     QMap<QString, QTcpSocket *>::iterator it;

      for(it=m_mapClient.begin();it!=m_mapClient.end();it++)
         {
             if(socket->peerAddress().toString() == it.key())
             {
                 m_mapClient.erase(it);
                 break;
             }
         }

}


完整代码 :点击下载

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值