Qt——实现两个Qt程序进行本地通信套接字(TCP)


前言

基于VS2019、Qt5.15.5,纯代码实现两个Qt程序进行本地通信套接字(TCP/IP或UDP)。


效果

LocalTCP

步骤

先创建服务端程序,在创建客户端程序。

一、创建服务端程序

1. 思路

服务器端使用QTcpServer用于端口监听,建立服务器;QTcpSocket用于建立连接后使用套接字进行通信。创建之后,始终让服务器端处于监听状态。
具体地:
侦听固定端口50000的“QTcpServer”对象。
当客户端连接时,服务器会创建一个新的“QTcpSocket”对象来管理连接。
服务器将三个double值(采样率、采样长度和下采样率)作为“QByteArray”发送给客户端。
服务器侦听来自客户端的“启动”或“停止”命令,并相应地设置一个标志,触发相应操作。
当客户端断开连接时,服务器会将标志设置为false并记录消息

2. 代码

2.1 Server.h
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_Server.h"
#include <QTcpServer>
#include <QTcpSocket>

class Server : public QMainWindow
{
    Q_OBJECT

public:
    Server(QWidget *parent = nullptr);
    ~Server();
    
private:
    Ui::ServerClass ui;
    QTcpServer* server = nullptr;       //监听 
    QTcpSocket* tcpSocket = nullptr;    //通信套接字
    bool startSendDataFlag = 0;
    //QList<QTcpSocket*> clients;			//暂时未用,后续多个客户端做准备

private slots:
    void onDisconnected();
};

2.2 Server.cpp
#include "Server.h"

Server::Server(QWidget *parent)
    : QMainWindow(parent)
{
    
    ui.setupUi(this);

    // 创建QTcpServer对象,并监听所有IP地址的50000端口
    server = new QTcpServer(this);
    server->listen(QHostAddress::Any, 50000);//Any可以换成LocalHost
    qDebug() << "Server is listening...";
    // 当有新连接时,执行lambda表达式
    connect(server, &QTcpServer::newConnection, [=]() {
        //取出建立好连接的套接字
        tcpSocket = server->nextPendingConnection();
        qDebug() << "Connected to client";
        
        //发送服务器端的采样率、采样长度、降采样等double类型信息给客户端,进行初始化使用
        double sampleRate = 1000.0; // replace with your sample rate
        double sampleLength = 100.0; // replace with your sample length
        double downSample = 2.0; // replace with your downsample rate

        // 将上述参数打包成QByteArray发送
        QByteArray data;
        QDataStream out(&data, QIODevice::WriteOnly);
        out << sampleRate << sampleLength << downSample;
        tcpSocket->write(data);     //写入数据到套接字
        tcpSocket->flush();         // 刷新缓冲区,确保数据发送
        // 当套接字有数据可读时,执行lambda表达式
        connect(tcpSocket, &QTcpSocket::readyRead, [=]() {
            //客户端会发送启动采集或停止采集给到服务器,服务器打开或者关闭startSendData
            QByteArray falg = tcpSocket->readAll();// 读取所有数据
            QString str(falg);// 将数据转换为字符串
            if (str == "start") {
                
                qDebug() << "Received start command from client";
                startSendDataFlag = true;
                qDebug() << "startSendDataFlag = " << startSendDataFlag;
            }
            else if (str == "stop") {
                
                qDebug() << "Received stop command from client";
                startSendDataFlag = false;
                qDebug() << "startSendDataFlag = "<< startSendDataFlag;
            }
        });
        // 当套接字断开连接时,调用onDisconnected槽函数
        connect(tcpSocket, &QTcpSocket::disconnected, tcpSocket, &QTcpSocket::deleteLater);
        connect(tcpSocket, &QTcpSocket::disconnected, this, &Server::onDisconnected);
    });
}

Server::~Server()
{
    if (tcpSocket) {
        //tcpSocket->abort();
        tcpSocket->deleteLater();
        tcpSocket = nullptr;
    }
    if (server) {
        server->deleteLater();
        server = nullptr;
    }
}
// 处理客户端断开连接的槽函数
void Server::onDisconnected()
{
    //tcpSocket->deleteLater();
    tcpSocket = nullptr;
    if (startSendDataFlag) {
        startSendDataFlag = false;
    }

    qDebug() << "Client disconnected";
    qDebug() << "startSendDataFlag = "<< startSendDataFlag;
}
/*
*释放“QTcpSocket”对象分配的系统资源
*防止意外重复使用同一个插座
*允许在新客户端连接时重新创建套接字
*/

二、创建客户端程序

1. 思路

客户端GUI包括一个带有两个操作的工具栏:“连接到服务器”和“启动/停止”。
当用户单击“连接到服务器”时,客户端将创建一个新的“QTcpSocket”对象,并连接到位于“localhost:50000”的服务器。
建立连接后,客户端会设置一个标志并启用“启动/停止”操作。
当用户单击“启动/停止”时,客户端会向服务器发送“启动”或“停止”命令。
客户端从服务器接收三个双值,并将它们记录到控制台。
当客户端与服务器断开连接时,客户端会将标志设置为false并记录消息

2. 代码

2.1 Client.h
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_Client.h"
#include <QTcpSocket>
class Client : public QMainWindow
{
    Q_OBJECT

public:
    Client(QWidget *parent = nullptr);
    ~Client();
private slots:
    void onConnected();
    void onReadyRead();
    void onDisconnected();
private:
    Ui::ClientClass ui;
    // 添加工具栏.
    QToolBar* toolBar = nullptr;
    QAction* connectServer = nullptr;
    QAction* startReceive = nullptr;

    QTcpSocket* socket = nullptr;

    bool connectServerFlag = 0;
    bool startReceiveFlag = 0;
    double CsampleRate = 0;
    double CsampleLength = 0;
    double CdownSample = 0; // 
};


2.2 Client.cpp
#include "Client.h"

Client::Client(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    //qDebug() << "startReceiveFlag = " << startReceiveFlag;
    connectServer = new QAction(QString::fromLocal8Bit("连接服务器"), this);
    startReceive = new QAction(QString::fromLocal8Bit("启动"), this);
    startReceive->setEnabled(false);
    //socket = new QTcpSocket(this);
    
    // 添加工具栏.
    toolBar = new QToolBar(this);
    // 指定停靠位置,如果第一个参数为Qt::LeftToolBarArea,就是停靠在左边的垂直工具栏.
    addToolBar(Qt::TopToolBarArea, toolBar);
    toolBar->setFloatable(true);// 设置允许浮动.
    toolBar->setMovable(true);  // 设置允许移动.
    toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);// 设置工具栏按钮只有图片.
    // 添加工具栏按钮.
    toolBar->addAction(connectServer);
    toolBar->addAction(startReceive);
    //toolBar->addAction(blueAction);
    // 添加分隔符.
    toolBar->addSeparator();
    //toolBar->addAction(microsoftYaHeiAction);

    connect(connectServer, &QAction::triggered, this, [this] {
        //
        if (!connectServerFlag) {
            qDebug() << "test1";
            
            if (socket) {
                socket->abort(); // cancel any existing connection attempt
                socket->deleteLater(); // delete the existing socket
                socket = nullptr;
                qDebug() << "delete existed socket";
                qDebug() << "please open server";
            }
            if (socket == nullptr) {
                qDebug() << "new";
                socket = new QTcpSocket(this);
            }
            //else {
            //    
            //}
            socket->connectToHost("localhost", 50000);
            connect(socket, &QTcpSocket::connected, this, &Client::onConnected);
            
            /*connect(socket, &QTcpSocket::disconnected, this, &Client::onDisconnected);
            connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
            socket->connectToHost("localhost", 50000);
            qDebug() << "creat new socket";*/
        }
        else {
            qDebug() << "test2";
            socket->disconnectFromHost();
            //onDisconnected(true);
            /*connectServerFlag = false;
            startReceiveFlag = false;
            startReceive->setText(QString::fromLocal8Bit("启动"));
            startReceive->setEnabled(false);
            connectServer->setText(QString::fromLocal8Bit("连接服务器"));*/
            //socket = nullptr;
        }
        });
    connect(startReceive, &QAction::triggered, this, [this] {
        if (connectServerFlag) {
            //qDebug() << "startReceiveFlag = " << startReceiveFlag;
            if (!startReceiveFlag) {
                //qDebug() << "start";
                QByteArray data;
                data.append("start");
                socket->write(data);
                startReceiveFlag = true;
                startReceive->setText(QString::fromLocal8Bit("停止"));
            }
            else {
                //qDebug() << "stop";
                QByteArray data;
                data.append("stop");
                socket->write(data);
                startReceiveFlag = false;
                startReceive->setText(QString::fromLocal8Bit("启动"));
            }
        }
        else {
            qDebug() << "请先与服务器连接";
        }
        });

    /*socket = new QTcpSocket(this);
    connect(socket, &QTcpSocket::connected, this, &Client::onConnected);
    connect(socket, &QTcpSocket::readyRead, this, &Client::onReadyRead);
    connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
    socket->connectToHost("localhost", 50000);*/
}

Client::~Client()
{
    // Delete the QTcpSocket object
    if (socket) {
        socket->abort(); // cancel any existing connection attempt
        socket->deleteLater(); // delete the existing socket
        socket = nullptr;
    }
    /*if (connectServer) {
        delete connectServer;
        connectServer = nullptr;
    }

    if (startReceive) {
        delete startReceive;
        startReceive = nullptr;
    }*/
    // Delete the GUI elements
    /*if (toolBar) {
        delete toolBar;
        toolBar = nullptr;
    }*/

    
}
void Client::onConnected()
{
    qDebug() << "Connected to server";
    connect(socket, &QTcpSocket::readyRead, this, &Client::onReadyRead);
    connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
    connect(socket, &QTcpSocket::disconnected, this, &Client::onDisconnected);
    
    
    
    
    qDebug() << "creat new socket";
    connectServerFlag = true;
    startReceive->setEnabled(true);
    connectServer->setText(QString::fromLocal8Bit("断开连接"));
    
    
}

void Client::onReadyRead() {
    QByteArray data = socket->readAll();
    QDataStream in(&data, QIODevice::ReadOnly);
    in >> CsampleRate >> CsampleLength >> CdownSample;
   
    qDebug() << "Received from server: "
        << "sampleRate:" << CsampleRate
        << ", sampleLength:" << CsampleLength
        << ", downSample:" << CdownSample;
}
void Client::onDisconnected()
{
    
    qDebug() << "Client disconnected from server";
    
    if (connectServerFlag) {
        connectServerFlag = false;
    }
    if (startReceiveFlag) {
        startReceiveFlag = false;
    }
    startReceive->setText(QString::fromLocal8Bit("启动"));
    startReceive->setEnabled(false);
    connectServer->setText(QString::fromLocal8Bit("连接服务器"));
    
    socket = nullptr; // set socket to nullptr here
    
}

三、主函数和解决方案资源管理器

Server端


#include "Server.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Server w;
    w.show();
    return a.exec();
}

在这里插入图片描述

Client端

#include "Client.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Client w;
    w.show();
    return a.exec();
}

在这里插入图片描述


其他设置

为了代码能跑起来,下面是我的一些设置,请参考。

Network设置

两边程序的项目属性设置都要勾选
在这里插入图片描述

调试设置

  1. 为了看qDebug信息,设置控制台输出
    在这里插入图片描述

代码和数据下载

我已经将我的代码和exe等文件上传,免费下载!支持开源!!
链接:https://pan.baidu.com/s/1-jn_o42HwzhpgvRBtPLM3w?pwd=yyds
提取码:yyds
–来自百度网盘超级会员V6的分享

总结

QTcpSocket对象的删除处理需要额外注意!

  • 24
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 创建本地 IP 套接字可以使用 QTcpSocket 类。下面是一个简单的示例代码,演示如何创建一个本地 IP 套接字: ```cpp #include <QtNetwork/QTcpSocket> #include <QtNetwork/QHostAddress> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket socket; socket.connectToHost(QHostAddress::LocalHost, 8080); return a.exec(); } ``` 在上面的示例,我们首先包含了 `QTcpSocket` 和 `QHostAddress` 头文件。然后,我们创建了一个 `QTcpSocket` 对象并调用了 `connectToHost()` 函数来连接到本地 IP 地址和端口号为 8080 的主机。在实际应用,你需要根据你的需求来更改本地 IP 地址和端口号。 需要注意的是,如果你希望创建一个本地服务器套接字,你需要使用 `QTcpServer` 类。在服务器端,你需要监听来自本地 IP 地址和端口号的连接请求。以下是一个简单的示例代码,演示如何创建一个本地服务器套接字: ```cpp #include <QtNetwork/QTcpServer> #include <QtNetwork/QHostAddress> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpServer server; server.listen(QHostAddress::LocalHost, 8080); return a.exec(); } ``` 在上面的示例,我们首先包含了 `QTcpServer` 和 `QHostAddress` 头文件。然后,我们创建了一个 `QTcpServer` 对象并调用了 `listen()` 函数来监听来自本地 IP 地址和端口号为 8080 的连接请求。在实际应用,你需要根据你的需求来更改本地 IP 地址和端口号。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值