Qt实现简单的TCP通信

 更新时间:2022年8月19日 17:01  点击:386 作者:小刘同学++

这段时间用到了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的设计:

三、运行结果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

原文出处:https://blog.csdn.net/qq_43420088/article/details/126225482

[!--infotagslink--]

相关文章

  • Springboot+TCP监听服务器搭建过程图解

    这篇文章主要介绍了Springboot+TCP监听服务器搭建过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-28
  • PC蓝牙通信C#代码实现

    这篇文章主要为大家详细介绍了PC蓝牙通信C#代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • C#串口通信程序实例详解

    在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports,创建C#串口通信程序的具体实现是如何的呢?让我们开始吧...2020-06-25
  • C# Socket的TCP通讯的实例代码

    本篇文章主要介绍了C# Socket的TCP通讯,socket通讯方式有两种:同步和异步,详细的介绍了这两种方法,有兴趣的可以了解一下。...2020-06-25
  • Qt 使用Poppler实现pdf阅读器的示例代码

    下面小编就为大家分享一篇Qt 使用Poppler实现pdf阅读器的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • C#基于TCP协议的服务器端和客户端通信编程的基础教程

    这篇文章主要介绍了C#基于TCP协议的服务器端和客户端通信编程的基础教程,文中讲解了C#中TCP编程主要相关的TcpListener类与TcpClient类用法,需要的朋友可以参考下...2020-06-25
  • 将matplotlib绘图嵌入pyqt的方法示例

    这篇文章主要介绍了将matplotlib绘图嵌入pyqt的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-27
  • 详解Vue 非父子组件通信方法(非Vuex)

    本篇文章主要介绍了详解Vue 非父子组件通信方法(非Vuex),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...2017-05-27
  • 详解React中组件之间通信的方式

    这篇文章主要介绍了React中组件之间通信的方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-07-27
  • android实现线程间通信的四种常见方式

    线程通信相信大家都不陌生了,但是你知道几种方法呢,本文主要介绍了android实现线程间通信的四种常见方式,分享给大家,需要的朋友们下面随着小编来一起学习学习吧...2021-05-13
  • 详解vue组件之间的通信

    这篇文章主要介绍了vue组件之间的通信,帮助大家更好的理解和学习前端的相关知识,感兴趣的朋友可以了解下...2020-08-30
  • vue前端开发层次嵌套组件的通信详解

    vue通过provide & inject两个关键字完成父组件向子孙组件直接传值,很像子类能够使用父类的属性一样方便。provide & inject一般用于多层之间的传值,两层之间还是使用props进行...2021-10-10
  • react之组件通信详解

    本篇文章主要介绍了React组件通信详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-10-15
  • Qt定时器和随机数详解

    在前一篇中我们介绍了键盘和鼠标事件,其实还有一个非常常用的事件,就是定时器事件,如果要对程序实现时间上的控制,那么就要使用到定时器。而随机数也是很常用的一个功能,在我们要想产生一个随机的结果时就要使用到随机数。本文我们就来简单介绍一下定时器和随机数。...2020-04-25
  • C#串口通信实现方法

    这篇文章主要介绍了C#串口通信实现方法,详细讲述了C#串口通信所涉及的数据接收与发送方法,以及相关的线程调用方法,是非常典型的应用,需要的朋友可以参考下...2020-06-25
  • 使用C#实现基于TCP和UDP协议的网络通信程序的基本示例

    这篇文章主要介绍了使用C#实现基于TCP和UDP协议的网络通信程序的示例,文中分别编写了基本的服务器端和客户端,代码十分简单,需要的朋友可以参考下...2020-06-25
  • C#中使用UDP通信实例

    这篇文章主要介绍了C#中使用UDP通信实例,非常实用的技巧,需要的朋友可以参考下...2020-06-25
  • 进程间通信之深入消息队列的详解

    本篇文章是对消息队列的应用进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • Python基础之Socket通信原理

    这篇文章主要介绍了Python基础之Socket通信原理,文中有非常详细的代码示例,对正在学习python基础的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-22
  • 一篇文章教你3分钟如何发布Qt程序

    这篇文章主要给大家介绍了关于教你3分钟如何发布Qt程序的相关资料,文中通过实例代码结束的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-08-24