《QT6/C++开发指南》网络/TCP通信/案例15-2

效果图:

在这里插入图片描述

知识点

在这里插入图片描述

tcpServer

在这里插入图片描述

.h

在这里插入图片描述

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include    <QTcpServer>
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    // 1、 标签栏变量
    QLabel  *labListen;         //状态栏标签
    QLabel  *labSocketState;    //状态栏标签:套接字的状态
    QTcpServer *tcpServer;      // TCP服务器:负责监听
    QTcpSocket *tcpSocket=nullptr;      //TCP通讯的Socket
    QString getLocalIP();       //获取本机IP地址
private slots:
    //自定义槽函数
    void    do_newConnection();         //关联QTcpServer的newConnection()信号
    void    do_clientConnected();       //客户端 socket 已连接
    void    do_clientDisconnected();    //客户端 socket 已断开
    void    do_socketReadyRead();       //读取socket传入的数据
    void    do_socketStateChange(QAbstractSocket::SocketState socketState);
    void on_actStart_triggered();

    void on_actStop_triggered();

    void on_btnSend_clicked();

    void on_actClear_triggered();

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

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

.cpp

重点代码:
在这里插入图片描述
在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHostInfo>
#include    <QtNetwork>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 1、标签栏放监听状态和Socket状态:
    labListen=new QLabel("监听状态:"); // 创建
    labListen->setMinimumWidth(150); // 设置
    ui->statusBar->addWidget(labListen); // 放

    labSocketState=new QLabel("Socket状态:");
    labSocketState->setMinimumWidth(200);
    ui->statusBar->addWidget(labSocketState);

    // 2、标题栏放本机IP地址
    QString localIP=getLocalIP();   //获取本机IP
    this->setWindowTitle(this->windowTitle()+"----本机IP地址:"+localIP);
    ui->comboIP->addItem(localIP);

    // 3、连接tcpServer和do_newConnection
    tcpServer=new QTcpServer(this);
    // 当有客户端接入时,tcpServer发送newConnection信号;此信号关联槽函数do_newConnection
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(do_newConnection()));
}

QString MainWindow::getLocalIP()
{//获取本机IPv4地址
    QString hostName=QHostInfo::localHostName();    // get :本地主机名
    QHostInfo hostInfo=QHostInfo::fromName(hostName);
    QString   localIP="";

    QList<QHostAddress> addList=hostInfo.addresses();  //本机IP地址列表
    if (addList.isEmpty())
        return localIP;

    foreach(const auto& aHost, addList)
        if (QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            localIP=aHost.toString();
            break;
        }
    return localIP;
}


void MainWindow::do_newConnection()
{
    // 通过nextPendingConnection()函数获取与连接的客户端进行通信的QTcpSocket 对象 tcpSocket,
    // 然后将 tcpSocket的几个信号与相应的槽函数连接起来。
    tcpSocket = tcpServer->nextPendingConnection(); //创建socket

    connect(tcpSocket, SIGNAL(connected()),this, SLOT(do_clientConnected()));
    do_clientConnected();   //执行一次槽函数,显示状态

    connect(tcpSocket, SIGNAL(disconnected()),this, SLOT(do_clientDisconnected()));

    connect(tcpSocket,&QTcpSocket::stateChanged,this,&MainWindow::do_socketStateChange);
    do_socketStateChange(tcpSocket->state());   //执行一次槽函数,显示状态
    // QTcpSocket对象接收到数据后会发射readyRead信号,连接槽函数
    connect(tcpSocket,SIGNAL(readyRead()),  this,SLOT(do_socketReadyRead()));
}

void MainWindow::do_socketReadyRead()
{//读取缓冲区的行文本
    while(tcpSocket->canReadLine()) // canReadLine()判断是否有新的一行数据需要读取
        ui->textEdit->appendPlainText("[in] "+tcpSocket->readLine());
}

void MainWindow::do_clientConnected()
{//客户端接入时
    ui->textEdit->appendPlainText("**client socket connected");
    ui->textEdit->appendPlainText("**peer address:"+
                                  tcpSocket->peerAddress().toString()); // 找到另一端的地址
    ui->textEdit->appendPlainText("**peer port:"+
                                  QString::number(tcpSocket->peerPort())); // 另一端的端口号
}

void MainWindow::do_clientDisconnected()
{//客户端断开连接时
    ui->textEdit->appendPlainText("**client socket disconnected");
    tcpSocket->deleteLater();
}

void MainWindow::do_socketStateChange(QAbstractSocket::SocketState socketState)
{//socket状态变化时
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
    }
}

MainWindow::~MainWindow()
{//析构函数:确保窗口关闭时断开与TCP客户端的socket连接
    if (tcpSocket != nullptr)
    {
        if (tcpSocket->state()==QAbstractSocket::ConnectedState)
            tcpSocket->disconnectFromHost();    //断开与客户端的连接
    }

    if (tcpServer->isListening())
        tcpServer->close();     //停止网络监听

    delete ui;
}

void MainWindow::on_actStart_triggered()
{//"开始监听"按钮
    QString  IP=ui->comboIP->currentText();  // 拿:IP地址字符串,如"127.0.0.1"
    quint16  port=ui->spinPort->value();     // 拿:端口
    QHostAddress   address(IP); // 将IP从字符串转成地址
    // 调用监听函数(主机地址,端口号)
    tcpServer->listen(address,port);    //开始监听
    //    tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
    ui->textEdit->appendPlainText("**开始监听...");
    ui->textEdit->appendPlainText("**服务器地址:"+tcpServer->serverAddress().toString());
    ui->textEdit->appendPlainText("**服务器端口:"+QString::number(tcpServer->serverPort()));

    ui->actStart->setEnabled(false);
    ui->actStop->setEnabled(true);
    labListen->setText("监听状态:正在监听");
}


void MainWindow::on_actStop_triggered()
{//"停止监听"按钮
    if (tcpServer->isListening())   //tcpServer正在监听
    {
        if (tcpSocket != nullptr)
            if (tcpSocket->state()==QAbstractSocket::ConnectedState)
                tcpSocket->disconnectFromHost();
        tcpServer->close();         //停止监听
        ui->actStart->setEnabled(true);
        ui->actStop->setEnabled(false);
        labListen->setText("监听状态:已停止监听");
    }
}



void MainWindow::on_btnSend_clicked()
{//"发送消息"按钮,发送一行字符串,以换行符结束
    // 没有连接上时
    if(tcpSocket == nullptr)
    {
        ui->textEdit->appendPlainText("没有连接成功");
        return;
    }
    QString  msg=ui->editMsg->text(); // get msg
    ui->textEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8(); // QString转成QByteArray
    str.append('\n');       //添加一个换行符
    tcpSocket->write(str); // 将str写入缓存区,要求QByteArray格式
}


void MainWindow::on_actClear_triggered()
{
    ui->textEdit->clear();
}


tcpClient

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QTcpSocket  *tcpClient;   //socket
    QLabel  *labSocketState;  //状态栏显示标签
    QString  getLocalIP();    //获取本机IP地址
private slots:
    //自定义槽函数
    void    do_connected();
    void    do_disconnected();
    void    do_socketStateChange(QAbstractSocket::SocketState socketState);
    void    do_socketReadyRead();//读取socket传入的数据


    void on_actConnect_triggered();

    void on_actDisconnect_triggered();

    void on_btnSend_clicked();

    void on_actClear_triggered();

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

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

.cpp

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

#include    <QHostInfo>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    tcpClient=new QTcpSocket(this);    //创建socket变量

    labSocketState=new QLabel("Socket状态:");  //状态栏标签
    labSocketState->setMinimumWidth(250);
    ui->statusBar->addWidget(labSocketState);

    QString localIP=getLocalIP();      //获取本机IP
    this->setWindowTitle(this->windowTitle()+"----本机IP地址:"+localIP);
    ui->comboServer->addItem(localIP);


    connect(tcpClient,SIGNAL(connected()),   this,SLOT(do_connected()));
    connect(tcpClient,SIGNAL(disconnected()),this,SLOT(do_disconnected()));

    connect(tcpClient,&QTcpSocket::stateChanged,this,&MainWindow::do_socketStateChange);

    connect(tcpClient,SIGNAL(readyRead()),   this,SLOT(do_socketReadyRead()));
}

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

QString MainWindow::getLocalIP()
{
    QString hostName=QHostInfo::localHostName();  //本地主机名
    QHostInfo   hostInfo=QHostInfo::fromName(hostName);
    QString   localIP="";
    QList<QHostAddress> addList=hostInfo.addresses();
    if (addList.isEmpty())
        return localIP;

    foreach(QHostAddress aHost, addList)
        if (QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            localIP=aHost.toString();
            break;
        }
    return localIP;
}

void MainWindow::do_connected()
{ //connected()信号的槽函数
    ui->textEdit->appendPlainText("**已连接到服务器");
    ui->textEdit->appendPlainText("**peer address:"+
                                  tcpClient->peerAddress().toString());
    ui->textEdit->appendPlainText("**peer port:"+
                                  QString::number(tcpClient->peerPort()));
    ui->actConnect->setEnabled(false);
    ui->actDisconnect->setEnabled(true);
}

void MainWindow::do_disconnected()
{//disConnected()信号的槽函数
    ui->textEdit->appendPlainText("**已断开与服务器的连接");
    ui->actConnect->setEnabled(true);
    ui->actDisconnect->setEnabled(false);
}

void MainWindow::do_socketStateChange(QAbstractSocket::SocketState socketState)
{//stateChange()信号的槽函数
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
    }
}

void MainWindow::do_socketReadyRead()
{//readyRead()信号的槽函数
    while(tcpClient->canReadLine())
        ui->textEdit->appendPlainText("[in] "+tcpClient->readLine());
}


void MainWindow::on_actConnect_triggered()
{//“连接服务器”按钮
    QString   addr=ui->comboServer->currentText(); // 拿:地址
    quint16   port=ui->spinPort->value(); // 拿:端口
    tcpClient->connectToHost(addr,port);
    //    tcpClient->connectToHost(QHostAddress::LocalHost,port);
}


void MainWindow::on_actDisconnect_triggered()
{//“断开连接”按钮
    if (tcpClient->state()==QAbstractSocket::ConnectedState)
        tcpClient->disconnectFromHost();
}


void MainWindow::on_btnSend_clicked()
{//“发送数据”按钮
    QString  msg=ui->editMsg->text(); // 拿:数据
    ui->textEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');
    tcpClient->write(str);
}


void MainWindow::on_actClear_triggered()
{
   ui->textEdit->clear();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值