当前位置:   article > 正文

QT -- TcpSocket实例,使用Qt中的tcp通信协议,构建客户端和服务端,实现局域网通信软件功能_qtcpsoket 用法

qtcpsoket 用法

1.简介

TCP通信协议是面向对象,可靠的连接服务,正因为这是它最大的特点,因此在诸多领域应用广泛,在使用Qt进行面向对象的设计的时候,也常常用到TCP通信,而在Qt中,TCP协议被封装成了一个更易调用的类。此篇博文将使用Qt中的TCP通信来实现客户端和服务端的连接交互通信,以此作为延伸。
在之前的一篇博文中 ,Linux中C语言构建TCP通信,使用了C语言对TCP协议进行调用,来实现客户端和服务端的通信连接。而Qt中的TCP通信连接步骤和C语言中原生tcp连接的步骤一样,大体都是分为以下大类

  • 创建套接字
  • 绑定本机地址和端口
  • 设置监听套接字
  • 主动向服务器(客户端)发送请求
  • 客户端(服务器)接受连接请求
  • 接受/发送数据
  • (双方)关闭套接字

区别在于,Qt中调用TCP的方式简单,可以实现如下的效果
在这里插入图片描述
以下是详细的实际实现

2.项目创建和界面构建

1)流程图

TCP协议通信逻辑图有下图,根据此逻辑图,可以更好的理解Qt中的TCP协议的调用
在这里插入图片描述

2)项目构建

创建widget项目,除自有界面外,再添加一个新的界面,构建如下图所示的项目文件树

在这里插入图片描述

3)界面构建

客户端界面构建

在这里插入图片描述
服务端界面构建

在这里插入图片描述

两个界面大体是构建上面是显示消息栏。下面是输入消息发送栏。

3.代码设计

1)项目pro添加

第一步需要在项目的pro文件中添加网络通信模块

QT       += network
  • 1

2)客户端设计

a. clientwidget.h

首先需要添加所需头文件,用于tcp通信

#include <QTcpSocket>
  • 1

之后是tcp通信的类的声明以及一个相应键盘事件的事件过滤器

private:
    QTcpSocket *tcpSocket;
protected:
    bool eventFilter(QObject *target, QEvent *event);//事件过滤器
};
  • 1
  • 2
  • 3
  • 4
  • 5
b.clientwdige.cpp

同样是添加所需工具头文件

#include <QHostAddress>
#include <QDebug>
#include <QTime>
#include <QKeyEvent>
  • 1
  • 2
  • 3
  • 4

之后是构造函数和部分相关函数的设计

ClientWidget::ClientWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClientWidget)
{
    ui->setupUi(this);
    this->setWindowTitle("客户端");
    this->resize(500,300);
    this->setMinimumSize(500,300);
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket,&QTcpSocket::connected,
            [=]()
            {
                ui->textEditRead->setText("与服务器成功连接");
                qDebug() << "连接成功";

            }
            );
    connect(tcpSocket,&QTcpSocket::readyRead,
            [=]()
            {
                QByteArray array = tcpSocket->readAll();
                ui->textEditRead->append(array);
            }
            );
    ui->ButtonSend->setFocus();
    ui->ButtonSend->setDefault(true);
    //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);
    ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数
}

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

void ClientWidget::on_ButtonConnect_clicked()
{
    //获取服务器端口和ip
    QString ip = ui->lineEditIp->text();
    qint16 port = ui->lineEditPort->text().toInt();
    //与服务器进行连接
    tcpSocket->connectToHost(QHostAddress(ip),port);
}

void ClientWidget::on_ButtonSend_clicked()
{
    //获取编辑框内容
    QTime cur_time = QTime::currentTime();
    QString str = ui->textEditWrite->toPlainText();
    QString time_info = cur_time.toString("hh:mm:ss");
    QString str_info = QString("客户端: %1 [%2]").arg(str).arg(time_info);
    //发送数据
    tcpSocket->write(str_info.toUtf8().data());
    ui->textEditWrite->clear();

    //ui->textEditWrite->setFocus();
}

void ClientWidget::on_ButtonClose_clicked()
{
    //主动断开连接
    tcpSocket->disconnectFromHost();
    ui->textEditRead->setText("与服务器断开连接!");
    tcpSocket->close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

3)服务端设计

a.serverwidget.h

添加头文件

#include <QTcpServer>   //监听套接字
#include <QTcpSocket>   //通信套接字
  • 1
  • 2

通信套接字声明实现和事件过滤器

private:
    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
protected:
    bool eventFilter(QObject *target, QEvent *event);//事件过滤器
  • 1
  • 2
  • 3
  • 4
  • 5
b.serverwidget.cpp

添加工具头文件

#include <QTime>
#include <QKeyEvent>
  • 1
  • 2

构造函数设计

ServerWidget::ServerWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ServerWidget)
{
    ui->setupUi(this);
    tcpServer = NULL;
    tcpSocket = NULL;
    //
    tcpServer  = new QTcpServer(this);
    tcpSocket = new QTcpSocket(this);
    tcpServer->listen(QHostAddress::Any,8888);
    this->setWindowTitle("服务器(端口:8888)");
    this->resize(500,300);
    this->setMinimumSize(500,300);

    connect(tcpServer,&QTcpServer::newConnection,
            [=]()
            {
                //取出建立好连接的套接字
                tcpSocket = tcpServer->nextPendingConnection();
                //获取对方的ip和端口s
                static QString ip = tcpSocket->peerAddress().toString();
                static qint16 port = tcpSocket->peerPort();
                QString temp = QString("[%1:%2] : 成功连接").arg(ip).arg(port);
                ui->textEditRead->setText(temp);

                connect(tcpSocket,&QTcpSocket::readyRead,
                        [=]()
                        {
                            //从通信套接字中取出内容
                            QByteArray array = tcpSocket->readAll();
                            ui->textEditRead->append(array);        //追加添加内容
                        }
                        );
            }
            );
//    connect(tcpSocket,&QTcpSocket::readyRead,
//            [=]()
//            {
//                //从通信套接字中取出内容
//                QByteArray array = tcpSocket->readAll();
//                ui->textEditRead->append(array);        //追加添加内容
//            }
//            );
    ui->ButtonSend->setFocus();
    ui->ButtonSend->setDefault(true);
    //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);
    ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

经此设计构建之后可以实现如上的功能操作,有此基础之后可以自定定义自己的服务器,如智能小车的控制,摄像头图像的传递识别等等

4.源代码附录

clientwidget.h
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
class ClientWidget;
}

class ClientWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ClientWidget(QWidget *parent = nullptr);
    ~ClientWidget();

private slots:
    void on_ButtonSend_clicked();

    void on_ButtonConnect_clicked();

    void on_ButtonClose_clicked();

private:
    Ui::ClientWidget *ui;

private:
    QTcpSocket *tcpSocket;
protected:
    bool eventFilter(QObject *target, QEvent *event);//事件过滤器
};

#endif // CLIENTWIDGET_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
clientwidget.cpp
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QHostAddress>
#include <QDebug>
#include <QTime>
#include <QKeyEvent>

ClientWidget::ClientWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClientWidget)
{
    ui->setupUi(this);
    this->setWindowTitle("客户端");
    this->resize(500,300);
    this->setMinimumSize(500,300);
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket,&QTcpSocket::connected,
            [=]()
            {
                ui->textEditRead->setText("与服务器成功连接");
                qDebug() << "连接成功";

            }
            );
    connect(tcpSocket,&QTcpSocket::readyRead,
            [=]()
            {
                QByteArray array = tcpSocket->readAll();
                ui->textEditRead->append(array);
            }
            );
    ui->ButtonSend->setFocus();
    ui->ButtonSend->setDefault(true);
    //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);
    ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数
}

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

void ClientWidget::on_ButtonConnect_clicked()
{
    //获取服务器端口和ip
    QString ip = ui->lineEditIp->text();
    qint16 port = ui->lineEditPort->text().toInt();
    //与服务器进行连接
    tcpSocket->connectToHost(QHostAddress(ip),port);
}

void ClientWidget::on_ButtonSend_clicked()
{
    //获取编辑框内容
    QTime cur_time = QTime::currentTime();
    QString str = ui->textEditWrite->toPlainText();
    QString time_info = cur_time.toString("hh:mm:ss");
    QString str_info = QString("客户端: %1 [%2]").arg(str).arg(time_info);
    //发送数据
    tcpSocket->write(str_info.toUtf8().data());
    ui->textEditWrite->clear();

    //ui->textEditWrite->setFocus();
}



void ClientWidget::on_ButtonClose_clicked()
{
    //主动断开连接
    tcpSocket->disconnectFromHost();
    ui->textEditRead->setText("与服务器断开连接!");
    tcpSocket->close();
}

bool ClientWidget::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->textEditWrite)
        {
            if(event->type() == QEvent::KeyPress)//回车键
            {
                 QKeyEvent *k = static_cast<QKeyEvent *>(event);

                 if(k->key() == Qt::Key_Return)
                 {
                     on_ButtonSend_clicked();
                     return true;
                 }
            }
        }
        return QWidget::eventFilter(target,event);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
serverwidget.h
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H

#include <QWidget>
#include <QTcpServer>   //监听套接字
#include <QTcpSocket>   //通信套接字

namespace Ui {
class ServerWidget;
}

class ServerWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ServerWidget(QWidget *parent = nullptr);
    ~ServerWidget();
protected:
    bool eventFilter(QObject *target, QEvent *event);//事件过滤器

private slots:
    void on_ButtonClose_clicked();

    void on_ButtonSend_clicked();

private:
    Ui::ServerWidget *ui;

private:
    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;

//    QString ip;
//    qint16 port;

};

#endif // SERVERWIDGET_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
serverwidget.cpp
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include <QTime>
#include <QKeyEvent>

ServerWidget::ServerWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ServerWidget)
{
    ui->setupUi(this);
    tcpServer = NULL;
    tcpSocket = NULL;
    //
    tcpServer  = new QTcpServer(this);
    tcpSocket = new QTcpSocket(this);
    tcpServer->listen(QHostAddress::Any,8888);
    this->setWindowTitle("服务器(端口:8888)");
    this->resize(500,300);
    this->setMinimumSize(500,300);

    connect(tcpServer,&QTcpServer::newConnection,
            [=]()
            {
                //取出建立好连接的套接字
                tcpSocket = tcpServer->nextPendingConnection();
                //获取对方的ip和端口s
                static QString ip = tcpSocket->peerAddress().toString();
                static qint16 port = tcpSocket->peerPort();
                QString temp = QString("[%1:%2] : 成功连接").arg(ip).arg(port);
                ui->textEditRead->setText(temp);

                connect(tcpSocket,&QTcpSocket::readyRead,
                        [=]()
                        {
                            //从通信套接字中取出内容
                            QByteArray array = tcpSocket->readAll();
                            ui->textEditRead->append(array);        //追加添加内容
                        }
                        );
            }
            );
//    connect(tcpSocket,&QTcpSocket::readyRead,
//            [=]()
//            {
//                //从通信套接字中取出内容
//                QByteArray array = tcpSocket->readAll();
//                ui->textEditRead->append(array);        //追加添加内容
//            }
//            );
    ui->ButtonSend->setFocus();
    ui->ButtonSend->setDefault(true);
    //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);
    ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数

}

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

bool ServerWidget::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->textEditWrite)
        {
            if(event->type() == QEvent::KeyPress)//回车键
            {
                 QKeyEvent *k = static_cast<QKeyEvent *>(event);

                 if(k->key() == Qt::Key_Return)
                 {
                     on_ButtonSend_clicked();
                     return true;
                 }
            }
        }
        return QWidget::eventFilter(target,event);

}


void ServerWidget::on_ButtonSend_clicked()
{
    if(tcpSocket == NULL)
    {
        return ;
    }
    //获取编辑区内容
    QTime cur_time = QTime::currentTime();
    QString str = ui->textEditWrite->toPlainText();
    QString time_info = cur_time.toString("hh:mm:ss");
    QString str_info = QString("服务器: %1 [%2]").arg(str).arg(time_info);
    tcpSocket->write(str_info.toUtf8().data());
    ui->textEditWrite->clear();
}

void ServerWidget::on_ButtonClose_clicked()
{
    if(tcpSocket == NULL)
    //主动与客户端断开连接
    tcpSocket->disconnectFromHost();

    static QString ip = tcpSocket->peerAddress().toString();
    static qint16 port = tcpSocket->peerPort();
    QString showtemp = QString("[%1:%2] : 断开连接").arg(ip).arg(port);
    ui->textEditRead->setText(showtemp);

    tcpSocket->close();
    //this->close();
    tcpSocket = NULL;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

5.源文件下载

详细效果,可戳传送门下载体验传送门

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/187372
推荐阅读
相关标签
  

闽ICP备14008679号