通过QT进行服务器和客户端之间的网络通信

客户端

client.pro

复制代码
#-------------------------------------------------
#
# Project created by QtCreator 2024-07-02T14:11:20
#
#-------------------------------------------------

QT       += core gui network   #网络通信

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = client
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

widget.h

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

    void InitClient();

private slots:
    void on_connect_bt_clicked();
    void on_send_bt_clicked();
    void OnReadData();

private:
    Ui::Widget *ui;

    QTcpSocket *m_pSocket;
};

#endif // WIDGET_H

main.cpp

复制代码
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.InitClient();
    w.show();

    return a.exec();
}

widget.cpp

复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>          //Qt 提供的输出调试信息的工具。
#include <QHostAddress>

Widget::Widget(QWidget *parent) :   //Widget类继承自QWidget
    QWidget(parent),
    ui(new Ui::Widget) //通过ui对象初始化界面布局
{
    ui->setupUi(this);
    m_pSocket = NULL;     //初始化m_pSocket为NULL
}

Widget::~Widget()      //析构函数释放了ui对象。
{
    delete ui;
}

void Widget::InitClient()       //设置界面初始状态,创建串口对象
{
    qDebug() << "Widget::InitClient() enter";
    if (NULL == m_pSocket)
    {
        m_pSocket = new QTcpSocket(this);   //QTcpSocket是Qt提供的用于TCP网络通信的类
        connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(OnReadData()));
        //readyRead()当socket接收到新的数据时发出的信号,SIGNAL()是一个宏,将信号转换为字符串形式。this是信号的发送者。
        //当m_pSocket对象接收到数据时,会触发readyRead()信号,然后调用当前类的OnReadData()槽函数来处理这些接收到的数据
    }
    qDebug() << "Widget::InitClient() exit";
}

void Widget::on_connect_bt_clicked()   //当按钮connect_bt被点击时触发
{
    qDebug() << "Widget::on_connect_bt_clicked() enter";

    QString strIP = ui->ip_edit->text();   //获取用户输入的IP地址
    QString strPort = ui->port_edit->text();
    qDebug() << strIP << " " << strPort;
    if (strIP.length() == 0 || strPort.length() == 0)  //检查用户输入的有效性,如果IP或端口号为空,则输出错误信息并返回
    {
        qDebug() << "input error";
        return;
    }

    if (NULL == m_pSocket)      //检查m_pSocket是否为NULL,如果是则输出错误信息并返回
    {
        qDebug() << "socket error";
        return;
    }

    m_pSocket->connectToHost(QHostAddress("127.0.0.1"), strPort.toShort());
    //使用m_pSocket->connectToHost()连接到指定的主机地址(这里是本地地址 "127.0.0.1")和端口号

    if (m_pSocket->waitForConnected(3000))
    //使用m_pSocket->waitForConnected(3000)等待连接建立,超时时间为3000毫秒(3秒)
    {
        qDebug() << "connect ok";
    }
    else
    {
        qDebug() << "connect error";
    }
    qDebug() << "Widget::on_connect_bt_clicked() exit";
}

void Widget::on_send_bt_clicked()
{
    qDebug() << "Widget::on_send_bt_clicked() enter";
    QString strData = ui->send_edit->text();
    if (strData.length() == 0)
    {
        qDebug() << "input error";
        return;
    }
    if (NULL == m_pSocket)
    {
        qDebug() << "socket error";
        return;
    }
    m_pSocket->write(strData.toStdString().data());    //发送字符串形式的数据到已连接的服务器端
    qDebug() << "Widget::on_send_bt_clicked() exit";
}

void Widget::OnReadData()
{
    QByteArray arr = m_pSocket->readAll();    //读取所有接收到的数据,并将其存储arr中
    qDebug() << arr;
}

widget.ui

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>692</width>
    <height>468</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>50</x>
     <y>60</y>
     <width>72</width>
     <height>15</height>
    </rect>
   </property>
   <property name="text">
    <string>ip</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="ip_edit">
   <property name="geometry">
    <rect>
     <x>100</x>
     <y>60</y>
     <width>181</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="label_2">
   <property name="geometry">
    <rect>
     <x>40</x>
     <y>100</y>
     <width>72</width>
     <height>15</height>
    </rect>
   </property>
   <property name="text">
    <string>port</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="port_edit">
   <property name="geometry">
    <rect>
     <x>100</x>
     <y>100</y>
     <width>181</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QPushButton" name="connect_bt">
   <property name="geometry">
    <rect>
     <x>350</x>
     <y>90</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>connect</string>
   </property>
  </widget>
  <widget class="QPushButton" name="send_bt">
   <property name="geometry">
    <rect>
     <x>350</x>
     <y>150</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>send</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="send_edit">
   <property name="geometry">
    <rect>
     <x>100</x>
     <y>160</y>
     <width>181</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

服务器

server.pro

复制代码
#-------------------------------------------------
#
# Project created by QtCreator 2024-07-02T09:20:48
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = server
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

widget.h

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

    void InitServer();

private slots:
    void OnNewConnection();
    void OnReadyData();

    void on_listen_bt_clicked();

private:
    Ui::Widget *ui;
    QTcpServer *m_pServer;
};

#endif // WIDGET_H

main.cpp

复制代码
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.InitServer();
    w.show();

    return a.exec();
}

widget.cpp

复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QHostAddress>
#include <QTcpSocket>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_pServer = NULL;
}

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

void Widget::InitServer()
{
    qDebug() << "Widget::InitServer() enter";
    if (NULL == m_pServer)
    {
        m_pServer = new QTcpServer(this);
        connect(m_pServer, SIGNAL(newConnection()), this, SLOT(OnNewConnection()));
    }
    qDebug() << "Widget::InitServer() exit";
}

void Widget::OnNewConnection()
{
    qDebug() << "new connection";
    QTcpSocket *pTmp = m_pServer->nextPendingConnection();  //获取下一个挂起的连接
    if (NULL != pTmp)
    {
        connect(pTmp, SIGNAL(readyRead()), this, SLOT(OnReadyData()));
        //当这个客户端socket有数据可读时,就会调用OnReadyData()函数
    }
}

void Widget::OnReadyData()
{
    qDebug() << "read data";
    QTcpSocket *pTmp = (QTcpSocket *)sender();   //获取信号的发送者
    if (NULL == pTmp)
    {
        qDebug() << "socket error";
        return;
    }
    QByteArray arr = pTmp->readAll();  //读取所有接收到的数据
    //qDebug() << arr;

    QString strData = ui->textEdit->toPlainText();  //将接收到的数据显示在界面中
    strData.append("recv : ");  //追加数据recv :
    strData.append(arr);
    strData.append("\n");
    ui->textEdit->setText(strData);
    pTmp->write(arr);   //将接收到的数据原样发送回客户端
}

void Widget::on_listen_bt_clicked()
{
    qDebug() << "Widget::on_listen_bt_clicked() enter";
    if (NULL == m_pServer)
    {
        return;
    }
    QString strIP = ui->ip_edit->text();
    QString strPort = ui->port_edit->text();
    if (strIP.length() == 0 || strPort.length() == 0)
    {
        qDebug() << "input error";
        return;
    }
    bool bRet = m_pServer->listen(QHostAddress(strIP), strPort.toShort());   //监听指定的IP地址和端口号
    if (bRet == true)
    {
        qDebug() << "server listen ok";
    }
    qDebug() << "Widget::on_listen_bt_clicked() enter";
}

widget.ui

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>893</width>
    <height>629</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>80</x>
     <y>60</y>
     <width>72</width>
     <height>15</height>
    </rect>
   </property>
   <property name="text">
    <string>ip</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="ip_edit">
   <property name="geometry">
    <rect>
     <x>140</x>
     <y>60</y>
     <width>221</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QLineEdit" name="port_edit">
   <property name="geometry">
    <rect>
     <x>140</x>
     <y>100</y>
     <width>221</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="label_2">
   <property name="geometry">
    <rect>
     <x>80</x>
     <y>100</y>
     <width>72</width>
     <height>15</height>
    </rect>
   </property>
   <property name="text">
    <string>port</string>
   </property>
  </widget>
  <widget class="QPushButton" name="listen_bt">
   <property name="geometry">
    <rect>
     <x>400</x>
     <y>100</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>listen</string>
   </property>
  </widget>
  <widget class="QTextEdit" name="textEdit">
   <property name="geometry">
    <rect>
     <x>60</x>
     <y>190</y>
     <width>761</width>
     <height>401</height>
    </rect>
   </property>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

测试

相关推荐
历程里程碑1 分钟前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
李日灐5 分钟前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树
汉克老师11 分钟前
GESP2025年6月认证C++二级( 第一部分选择题(1-8))
c++·循环结构·表达式·分支结构·gesp二级·gesp2级
rainbow688916 分钟前
C++高性能框架Drogon:后端开发新标杆
c++
Q741_14718 分钟前
C++ 优先级队列 大小堆 模拟 力扣 703. 数据流中的第 K 大元素 每日一题
c++·算法·leetcode·优先级队列·
Yu_Lijing1 小时前
网络复习篇——网络基础(一)
网络·c++·笔记
Bella的成长园地1 小时前
为什么c++中的条件变量的 wait() 函数需要配合while 循环或谓词?
c++·面试
charlee441 小时前
为什么现代 C++ 库都用 PIMPL?一场关于封装、依赖与安全的演进
c++·智能指针·raii·pimpl·编译防火墙·封装设计
MSTcheng.1 小时前
CANN ops-math算子的跨平台适配与硬件抽象层设计
c++·mfc
code monkey.1 小时前
【Linux之旅】Linux 进程间通信(IPC)全解析:从管道到共享内存,吃透进程协作核心
linux·c++·ipc