QT5实现简单的TCP通信

这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。

使用QT的网络套接字需要.pro文件中加入一句:

QT       += network

一、客户端

1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:

(1)创建QTcpSocket套接字对象

socket = new QTcpSocket();

(2)使用这个对象连接服务器

socket->connectToHost(IP, port);

(3)使用write函数向服务器发送数据

socket->write(data);

(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取缓冲区数据
    buffer = socket->readAll();
}

(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)

socket->disconnectFromHost();

2、以下是客户端的例程

首先是mainwindow.h文件:

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:

    void on_pushButton_Connect_clicked();

    void on_pushButton_Send_clicked();

    void socket_Read_Data();

    void socket_Disconnected();

private:
    Ui::MainWindow *ui;
    QTcpSocket *socket;
};

#endif // MAINWINDOW_H

然后是mainwindow.cpp文件:

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    socket = new QTcpSocket();

    //连接信号槽
    QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);

    ui->pushButton_Send->setEnabled(false);
    ui->lineEdit_IP->setText("127.0.0.1");
    ui->lineEdit_Port->setText("8765");

}

MainWindow::~MainWindow()
{
    delete this->socket;
    delete ui;
}

void MainWindow::on_pushButton_Connect_clicked()
{
    if(ui->pushButton_Connect->text() == tr("连接"))
    {
        QString IP;
        int port;

        //获取IP地址
        IP = ui->lineEdit_IP->text();
        //获取端口号
        port = ui->lineEdit_Port->text().toInt();

        //取消已有的连接
        socket->abort();
        //连接服务器
        socket->connectToHost(IP, port);

        //等待连接成功
        if(!socket->waitForConnected(30000))
        {
            qDebug() << "Connection failed!";
            return;
        }
        qDebug() << "Connect successfully!";

        //发送按键使能
        ui->pushButton_Send->setEnabled(true);
        //修改按键文字
        ui->pushButton_Connect->setText("断开连接");
    }
    else
    {
        //断开连接
        socket->disconnectFromHost();
        //修改按键文字
        ui->pushButton_Connect->setText("连接");
        ui->pushButton_Send->setEnabled(false);
    }
}

void MainWindow::on_pushButton_Send_clicked()
{
    qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
     //获取文本框内容并以ASCII码形式发送
    socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    socket->flush();
}

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取缓冲区数据
    buffer = socket->readAll();
    if(!buffer.isEmpty())
    {
        QString str = ui->textEdit_Recv->toPlainText();
        str+=tr(buffer);
        //刷新显示
        ui->textEdit_Recv->setText(str);
    }
}

void MainWindow::socket_Disconnected()
{
    //发送按键失能
    ui->pushButton_Send->setEnabled(false);
    //修改按键文字
    ui->pushButton_Connect->setText("连接");
    qDebug() << "Disconnected!";
}

最后是ui的设计:

二、服务器

1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:

(1)创建QTcpSever对象

server = new QTcpServer();

(2)侦听一个端口,使得客户端可以使用这个端口访问服务器

server->listen(QHostAddress::Any, port);

(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问

connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);

void MainWindow::server_New_Connect()
{
    //获取客户端连接
    socket = server->nextPendingConnection();
}

(4)使用socket的write函数向客户端发送数据

socket->write(data);

(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取缓冲区数据
    buffer = socket->readAll();
}

(6)取消侦听

server->close();

2、以下是服务器的例程

首先是mainwindow.h文件:

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_Listen_clicked();

    void on_pushButton_Send_clicked();

    void server_New_Connect();

    void socket_Read_Data();

    void socket_Disconnected();

private:
    Ui::MainWindow *ui;
    QTcpServer* server;
    QTcpSocket* socket;
};

#endif // MAINWINDOW_H

然后是mainwindow.cpp文件:

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->lineEdit_Port->setText("8765");
    ui->pushButton_Send->setEnabled(false);

    server = new QTcpServer();

    //连接信号槽
    connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
}

MainWindow::~MainWindow()
{
    server->close();
    server->deleteLater();
    delete ui;
}

void MainWindow::on_pushButton_Listen_clicked()
{
    if(ui->pushButton_Listen->text() == tr("侦听"))
    {
        //从输入框获取端口号
        int port = ui->lineEdit_Port->text().toInt();

        //监听指定的端口
        if(!server->listen(QHostAddress::Any, port))
        {
            //若出错,则输出错误信息
            qDebug()<<server->errorString();
            return;
        }
        //修改按键文字
        ui->pushButton_Listen->setText("取消侦听");
        qDebug()<< "Listen succeessfully!";
    }
    else
    {
/*
        //如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30)
        if(socket->state() == QAbstractSocket::ConnectedState)
        {
            //关闭连接
            socket->disconnectFromHost();
        }
*/
        socket->abort();
        //取消侦听
        server->close();
        //修改按键文字
        ui->pushButton_Listen->setText("侦听");
        //发送按键失能
        ui->pushButton_Send->setEnabled(false);
    }

}

void MainWindow::on_pushButton_Send_clicked()
{
    qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
    //获取文本框内容并以ASCII码形式发送
    socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    socket->flush();
}

void MainWindow::server_New_Connect()
{
    //获取客户端连接
    socket = server->nextPendingConnection();
    //连接QTcpSocket的信号槽,以读取新数据
    QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
    //发送按键使能
    ui->pushButton_Send->setEnabled(true);

    qDebug() << "A Client connect!";
}

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取缓冲区数据
    buffer = socket->readAll();
    if(!buffer.isEmpty())
    {
        QString str = ui->textEdit_Recv->toPlainText();
        str+=tr(buffer);
        //刷新显示
        ui->textEdit_Recv->setText(str);
    }
}

void MainWindow::socket_Disconnected()
{
    //发送按键失能
    ui->pushButton_Send->setEnabled(false);
    qDebug() << "Disconnected!";
}

最后是ui的设计:

三、运行结果

附上两个工程的下载链接:http://download.csdn.net/detail/u014695839/9810107

以上是根据这几天学习总结出的基于QT5的TCP通信的简单实现,如有错误希望能指出,欢迎各位多多交流!

 

  • 115
    点赞
  • 775
    收藏
    觉得还不错? 一键收藏
  • 85
    评论
Qt实现TCP通信,一般可以使用Qt提供的网络库Qt Network来实现。如果需要在应用程序中同时执行网络操作和其他操作,可以将网络操作放在一个独立的线程中执行,这样可以防止网络操作阻塞主线程。 继承QThread类可以方便地创建一个新线程,然后将网络操作放在新线程中执行。以下是一个简单的例子,展示如何使用继承QThread类的方式实现TCP通信: ```c++ #include <QTcpSocket> #include <QThread> class MyThread : public QThread { Q_OBJECT public: MyThread(QObject *parent = nullptr); void run() override; signals: void messageReceived(const QString &msg); private: QTcpSocket *m_socket; }; MyThread::MyThread(QObject *parent) : QThread(parent), m_socket(nullptr) { } void MyThread::run() { m_socket = new QTcpSocket(); m_socket->connectToHost("127.0.0.1", 8888); //连接服务器 if (m_socket->waitForConnected()) { //连接成功 emit messageReceived("Connected to server"); m_socket->write("Hello server"); //向服务器发送消息 if (m_socket->waitForReadyRead()) { //等待接收服务器返回的消息 QByteArray data = m_socket->readAll(); emit messageReceived(data); } } else { emit messageReceived("Failed to connect to server"); } m_socket->close(); delete m_socket; } //在主线程中创建MyThread对象,并监听它的信号 int main(int argc, char *argv[]) { QApplication app(argc, argv); MyThread thread; QObject::connect(&thread, &MyThread::messageReceived, [](const QString &msg){ qDebug() << msg; }); thread.start(); return app.exec(); } ``` 在这个例子中,MyThread类继承自QThread类,并在run()函数中执行TCP通信相关的操作。当连接服务器成功或失败时,MyThread对象会发出messageReceived信号,并传递相应的消息。 在主线程中创建MyThread对象,并监听它的信号,这样就可以在主线程中获取到TCP通信相关的消息了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值