通过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>

测试

相关推荐
过过过呀Glik1 分钟前
在 Ubuntu 上安装 Muduo 网络库的详细指南
linux·c++·ubuntu·boost·muduo
蜀黍@猿1 小时前
【C++ 基础】从C到C++有哪些变化
c++
Am心若依旧4091 小时前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
zh路西法1 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
c++·决策树·状态模式
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
lxyzcm2 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿2 小时前
C/C++基础错题归纳
c++
雨中rain2 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
ALISHENGYA3 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu3 小时前
现代C++锁介绍
c++·多线程·mutex