Qt tcp通信

服务端

思路

  • 显示桌面的主机是服务端。
  • 当服务端接收完客户端数据时会主动断开和客户端的连接。

客户端

思路

  • 被投放桌面的主机是服务端。
  • 客户端截图桌面,发送给服务端截图的大小和数据。
  • 客户端发送截图后,等待客户端断开连接(通过这个等待判断服务端是不是已经读取完图片了),然后再重新连接服务端。
  • 客户端启动后就隐藏程序窗口,后台执行

代码

服务端-mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QResizeEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void initClient();
    void receivePixmap();

protected:
    void resizeEvent(QResizeEvent *event);

private:
    Ui::MainWindow *ui;
    QTcpServer* tcp_server;
    QTcpSocket* tcp_client;
    int pixmapSize = 0;
    bool isNewPixmap = true;
    QByteArray pixmapData;
};
#endif // MAINWINDOW_H

服务端-mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#define PORT 43124

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //  设置显示桌面标签的布局大小
    ui->pixmapLabel->setGeometry(0,0,this->width(),this->height());
    this->tcp_server = new QTcpServer;
    //  鉴听端口
    this->tcp_server->listen(QHostAddress::Any,PORT);
    //  当有客户端连接时,发射newConnection()信号
    QObject::connect(this->tcp_server,SIGNAL(newConnection()),this,SLOT(initClient()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initClient(){
    //  获取客户端
    this->tcp_client = this->tcp_server->nextPendingConnection();
    //  当客户端向服务端发送数据时发射readyRead()信号
    QObject::connect(this->tcp_client,SIGNAL(readyRead()),this,SLOT(receivePixmap()));
}

#include <QByteArray>
#include <QPixmap>
#include <QBuffer>
#include <QIODevice>
#include <QImageReader>

void MainWindow::receivePixmap(){

    char readBuffer;

    //  如果是新的一张照片,则进入if,否则不进入
    if(this->isNewPixmap){
        char bufferSize[10];
        int len = this->tcp_client->read(bufferSize,sizeof(bufferSize));
        QString str;
        int i;
        for(i=0; i<len; i++){
            if(bufferSize[i] >= '0' && bufferSize[i] <= '9'){
                str.append(bufferSize[i]);
            }else{
                break;
            }
        }

        //  前面读取数据只是为了获得想要传过来的照片大小
        this->pixmapSize = str.toInt();

        //  但照片大小不一定装满10字节,故后面的属于照片的数据内容
        for(;i < len; i++){
            pixmapData.append(bufferSize[i]);
        }
        isNewPixmap = false;
    }

    //  如果照片数据没读完
    if(pixmapSize > pixmapData.size()){
        //  readALL 不一定能读完全部数据,所以这里表示读一部分数据
        QByteArray tempArray = this->tcp_client->readAll();
        QBuffer tempBuffer(&tempArray);
        tempBuffer.open(QIODevice::ReadOnly);
        int tempSize = tempBuffer.size();
        //  从头开始读取
        tempBuffer.seek(0);
        while(tempSize > 0){
            tempBuffer.getChar(&readBuffer);
            //  把部分数据加入到照片数据
            pixmapData.append(readBuffer);
            tempSize--;
        }
    }

    //  如果照片数据读完了
    if(pixmapSize == pixmapData.size()){
        QBuffer buffer(&pixmapData);
        buffer.open( QIODevice::ReadOnly);
        QImageReader reader(&buffer, "png");
        QImage image = reader.read();

        //  显示照片
        ui->pixmapLabel->setPixmap(QPixmap::fromImage(image,Qt::AutoColor).scaled(
                                 ui->pixmapLabel->size()));

        //  开始接收下一张照片
        isNewPixmap = true;
        this->pixmapData.clear();

        //  断开客户端与服务端的连接
        this->tcp_client->disconnectFromHost();
    }
}

void MainWindow::resizeEvent(QResizeEvent *event){
    //  窗口大小发生任何改变时,改变pixmapLabel大小,实现自适应窗口
    ui->pixmapLabel->setGeometry(0,0,this->width(),this->height());
}


客户端-mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void sendPixmap();

private:
    Ui::MainWindow *ui;
    QTcpSocket* tcp_server;
};
#endif // MAINWINDOW_H

客户端-mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#define HOST "192.168.3.236"
#define PORT 43124

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->tcp_server = new QTcpSocket;
    //  连接到服务端
    this->tcp_server->connectToHost(HOST,PORT);
    //  连接成功发送connected()信号
    QObject::connect(this->tcp_server,SIGNAL(connected()),this,SLOT(sendPixmap()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

#include <QScreen>
#include <QPixmap>
#include <QApplication>
#include <QDesktopWidget>
#include <QGuiApplication>
#include <QImage>
#include <QImageReader>
#include <QByteArray>
#include <QBuffer>
#include <QThread>

void MainWindow::sendPixmap(){
    QScreen* screen = QGuiApplication::primaryScreen();
    //  获取桌面截图图片
    QPixmap pixmap = screen->grabWindow(QApplication::desktop()->winId());
    QImage image = pixmap.toImage();

    QByteArray ba;
    QBuffer buffer(&ba);
    buffer.open(QIODevice::WriteOnly);
    //  把截图的数据写入buffer
    image.save(&buffer, "PNG");

    //  把 截图的数据的大小 发送给服务器
    this->tcp_server->write(QString::number(ba.size()).toLatin1().data());
    //  把 截图的数据 发送给服务器
    this->tcp_server->write(ba);

    this->tcp_server->flush();

    //  服务端接收完数据会和客户端断开连接
    //  等待服务端接收完成
    this->tcp_server->waitForDisconnected();

    //  重新连接,连接成功发送connected()信号,重新执行sendPixmap方法
    this->tcp_server->connectToHost(HOST,PORT);
}




需要注意的是客户端在启动的时候把自己窗口隐藏住

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    //  该程序窗口一开始便隐藏,不显示,后台执行
    w.hide();
    return a.exec();
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值