基于TCP Qt的网络通信

在标准 C++ 没有提供专门用于套接字通信的类,所以只能使用操作系统提供的基于 C 的 API 函数,基于这些 C 的 API 函数我们也可以封装自己的 C++ 类 , 但是Qt 提供了封装好的套接字通信类:

  • QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接
  • QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接

这两个套接字通信类都属于网络模块 network ,使用前切记在项目的 .pro文件中添加 network 模块

文章目录

  • 基于TCP Qt的网络通信
    • 1、QTcpSever
      • 1.1 成员函数
      • 1.2 信号
    • 2、 QTcpSocket
      • 2.1 成员函数
      • 2.2 信号
    • 3、 通信流程
      • 3.1 服务器端
      • 3.2 客户端

1、QTcpSever

QTcpServer 类用于监听客户端连接以及和客户端建立连接,在使用之前先介绍一下这个类提供的一些常用 API 函数:

1.1 成员函数

  • 构造函数
QTcpServer::QTcpServer(QObject *parent = Q_NULLPTR);
  • 给监听的套接字设置监听
bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
// 判断当前对象是否在监听, 是返回true,没有监听返回false
bool QTcpServer::isListening() const;
// 如果当前对象正在监听返回监听的服务器地址信息, 否则返回 QHostAddress::Null
QHostAddress QTcpServer::serverAddress() const;
// 如果服务器正在侦听连接,则返回服务器的端口; 否则返回0
quint16 QTcpServer::serverPort() const

参数:

  1. address: 通过类 QHostAddress 可以封装 IPv4 、 IPv6 格式的 IP地址,QHostAddress :: Any 表示自动绑定;
  2. port: 端口号 , 指定为 0 表示随机绑定一个可用端口;
  3. 返回值: 绑定失败返回 false , 成功 true;
  • 得到和客户端建立连接之后用于通信的 QTcpSocket 套接字对象,它是 QTcpServer 的一个子对象,当 QTcpServer 对象析构的时候会自动析构这个子对象,当然也可自己手动析构,建议用完之后自己手动析构这个通信的 QTcpSocket 对象。
QTcpSocket *QTcpServer::nextPendingConnection();
  • 阻塞等待客户端发起的连接请求,不推荐在单线程程序中使用,建议使用非阻塞方式处理新连接,即使用信号 newConnection()
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR);

参数:

  1. mes: 指定阻塞的最大时间 , 单位毫秒;
  2. timeout: 传出参数,如果操作超时 timeout 为 true,没有超时 timeout 为 false;

1.2 信号

  • 当接受新连接导致错误时,将发射如下信号。socketError 参数描述了发生的错误相关的信息;
[signal] void QTcpServer::acceptError(QAbstractSocket::SocketError socketError);
  • 每次有新连接可用时都会发出 newConnection () 信号。
[signal] void QTcpServer::newConnection();

2、 QTcpSocket

QTcpSocket 是一个套接字通信类,不管是客户端还是服务器端都需要使用。在 Qt 中发送和接收数据也属于 IO 操作(网络 IO),先来看一下这个类的继承关系:

QTcpSocket 继承于  QAbstractSocket  继承于  QIODevice

2.1 成员函数

  • 构造函数
QTcpSocket::QTcpSocket(QObject *parent = Q_NULLPTR);
  • 连接服务器,需要指定服务器端绑定的IP和端口信息。
[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);[virtual] void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite);

在 Qt 中不管调用读操作函数接收数据,还是调用写函数发送数据,操作的对象都是本地的由 Qt 框架维护的一块内存。因此,调用了发送函数数据不一定会马上被发送到网络中,调用了接收函数也不是直接从网络中接收数据,关于底层的相关操作是不需要使用者来维护的

  • 接受数据
// 指定可接收的最大字节数 maxSize 的数据到指针 data 指向的内存中
qint64 QIODevice::read(char *data, qint64 maxSize);
// 指定可接收的最大字节数 maxSize,返回接收的字符串
QByteArray QIODevice::read(qint64 maxSize);
// 将当前可用操作数据全部读出,通过返回值返回读出的字符串
QByteArray QIODevice::readAll();
  • 发送数据
// 发送指针 data 指向的内存中的 maxSize 个字节的数据
qint64 QIODevice::write(const char *data, qint64 maxSize);
// 发送指针 data 指向的内存中的数据,字符串以 \0 作为结束标记
qint64 QIODevice::write(const char *data);
// 发送参数指定的字符串
qint64 QIODevice::write(const QByteArray &byteArray);

2.2 信号

在使用 QTcpSocket 进行套接字通信的过程中,如果该类对象发射出 readyRead() 信号,说明对端发送的数据达到了,之后就可以调用 read 函数接收数据了

[signal] void QIODevice::readyRead();
  • 调用 connectToHost() 函数并成功建立连接之后发出 connected() 信号
[signal] void QAbstractSocket::connected();
  • 在套接字断开连接时发出 disconnected() 信号
[signal] void QAbstractSocket::disconnected();

3、 通信流程

代码百度连接,自行提取

链接:https://pan.baidu.com/s/1W-ixxxt66IsmDLXUTD0PsA
提取码:1234

3.1 服务器端

  1. 创建套接字服务器 QTcpServer 对象
  2. 通过 QTcpServer 对象设置监听,即:QTcpServer::listen()
  3. 基于 QTcpServer::newConnection() 信号检测是否有新的客户端连接
  4. 如果有新的客户端连接调用 QTcpSocket *QTcpServer::nextPendingConnection() 得到通信的套接字对象
  5. 使用通信的套接字对象 QTcpSocket 和客户端进行通信

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QString>
#include <QLabel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_setlisten_clicked();void on_pushButton_clicked();private:Ui::MainWindow *ui;QTcpServer* m_s;QTcpSocket* m_tcp;QLabel* m_status;
};#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("服务器");ui->pushButton->setDisabled(true); // 初始化连接前,不能按发送按钮m_s = new QTcpServer(this);// 创建监听的套接字ui->port->setText("8899"); // 默认资源connect(m_s ,&QTcpServer::newConnection ,this,[=](){// 创建用于通信的套接字m_tcp = m_s->nextPendingConnection();m_status->setPixmap(QPixmap(":/green.png").scaled(20,20));// 切换状态栏图片// 检测是否可以接受数据connect(m_tcp,&QTcpSocket::readyRead,this,[=](){QByteArray data = m_tcp->readAll();ui->record->append("客户端 : " + data);});// 断开连接connect(m_tcp,&QTcpSocket::disconnected ,this,[=](){m_tcp->close();m_tcp->deleteLater(); // 封装 deletem_status->setPixmap(QPixmap(":/red.png").scaled(20,20));ui->pushButton->setDisabled(true);});// 切换发送按钮状态ui->pushButton->setDisabled(false);});// 状态栏m_status = new QLabel;m_status->setPixmap(QPixmap(":/red.png").scaled(20,20));ui->statusBar->addWidget(new QLabel("连接状态: "));ui->statusBar->addWidget(m_status);
}MainWindow::~MainWindow()
{delete ui;
}// 启动监听服务按钮
void MainWindow::on_setlisten_clicked()
{unsigned short port = ui->port->text().toUShort();m_s->listen(QHostAddress::Any ,port); // 设置监听ui->setlisten->setDisabled(true);}// 发送数据按钮
void MainWindow::on_pushButton_clicked()
{QString msg = ui->msg->toPlainText();m_tcp->write(msg.toUtf8()); // 输入客户端ui->record->append("服务器 : " + msg);}

3.2 客户端

  1. 创建通信的套接字类 QTcpSocket 对象
  2. 使用服务器端绑定的 IP 和端口连接服务器 QAbstractSocket::connectToHost()
  3. 使用 QTcpSocket 对象和服务器进行通信

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include <QTcpSocket>
#include <QString>
#include <QLabel>
#include <QHostAddress>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();void readData();private slots:void on_pushButton_clicked();void on_connect_clicked();void on_disconnect_clicked();private:Ui::MainWindow *ui;QTcpSocket* m_tcp;QLabel* m_status;
};#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowIcon(QIcon(":/m4.ico"));setWindowTitle("客户端");ui->disconnect->setDisabled(true); // 初始时 ,断开连接按钮不可用ui->port->setText("30003"); // 默认端口ui->ip->setText("192.168.79.129"); // 默认ipui->msg->setPlaceholderText("请输入指令");// 创建通信的套接字m_tcp =new QTcpSocket(this);// 接受到服务端消息connect(m_tcp,&QTcpSocket::readyRead,this,[=](){QByteArray data = m_tcp->readAll();// ui->record->append("服务器 : " + data);// readData();});// 服务器端断开连接connect(m_tcp,&QTcpSocket::disconnected ,this,[=](){m_tcp->close();//m_tcp->deleteLater(); // 封装 deletem_status->setPixmap(QPixmap(":/red.png").scaled(20,20));ui->record->append("已经和服务器断开连接....");ui->connect->setDisabled(false);// 设置连接按钮不可用ui->disconnect->setDisabled(true);});// 检测连接状态connect(m_tcp,&QTcpSocket::connected ,this,[this](){m_status->setPixmap(QPixmap(":/green.png").scaled(20,20));ui->record->append("连接服务器成功...");ui->connect->setDisabled(true);ui->disconnect->setDisabled(false);});// 状态栏m_status = new QLabel;m_status->setPixmap(QPixmap(":/red.png").scaled(20,20));ui->statusBar->addWidget(new QLabel("连接状态: "));ui->statusBar->addWidget(m_status);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::readData()
{QByteArray byteArray;//临时变量,用来存储每次从机械臂读进来的数据byteArray.resize(this->m_tcp->bytesAvailable());//先设置每次读取的大小为可接收缓存的大小int byteRead = this->m_tcp->read(byteArray.data(), byteArray.size());//把缓存区所有数据读取回来,可以用readAll替代,但是现在用的函数可以判断读取结果if (byteRead == -1) {//读取错误ui->record->append("read data from robot error!") ;return;} else if (byteRead == 0) {//没读到东西ui->record->append("read data from robot error!") ;return;}
}// 发送数据按钮
void MainWindow::on_pushButton_clicked()
{QString msg = ui->msg->toPlainText();m_tcp->write(msg.toUtf8()+"\n"); // 输入客户端ui->record->append("客户端 : " + msg);ui->msg->clear();
}// 连接服务器按钮
void MainWindow::on_connect_clicked()
{QString ip = ui->ip->text();unsigned short port = ui->port->text().toUShort();m_tcp->connectToHost(QHostAddress(ip) , port);
}// 断开连接
void MainWindow::on_disconnect_clicked()
{m_tcp->close();ui->disconnect->setDisabled(true);ui->connect->setDisabled(false);
}

Qt 的网络通信(TCP)相关推荐

  1. 03 - Qt 多线程网络通信——套接字

    文章序言 日志1.0 :在QT中如何使用TCP协议进行套接字通信(即指网络通信) TCP 和 UDP是传输层协议, 二者的区别: TCP是面向连接的流式传输协议:TCP传输, 数据安全: UDP是面向 ...

  2. Qt中的TCP客户端编程

    文章目录 1 Qt中的TCP客户端编程 1.1 TCP客户端编程介绍 1.2 QTcpSocket的同步编程 1.3 QTcpSocket的异步编程 1 Qt中的TCP客户端编程 1.1 TCP客户端 ...

  3. qt android 网络编程实例,QT网络编程Tcp下C/S架构的即时通信实例

    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include #include # ...

  4. Qt网络编程——TCP

    Qt网络编程--TCP 1. 概念 2. 服务器 3. 客户端 4. TCP服务器和客户端互传文件 5. 资源下载 1. 概念 TCP(Transmission Control Protocol, 传 ...

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

    Qt中使用Tcp构建通信客户端实现聊天信息发送连接等 1.简介 2.项目创建和界面构建 1)流程图 2)项目构建 3)界面构建 3.代码设计 1)项目pro添加 2)客户端设计 a. clientwi ...

  6. 默蓝网络通信TCP/HTTP测试工具介绍

    默蓝网络通信TCP/HTTP测试工具介绍 默蓝网络通信TCP/HTTP测试工具为广大技术开发人员提供的通信测试工具,其具备如下功能: 1.支持TCP/IP协议的网络通信,TCP服务端和客户端,可单条发 ...

  7. 用QT写一个TCP通信助手(一、界面设计)

    一.新建工程 创建QT widgets工程 修改项目名称TCPAssistant,下一步下一步直到出现此界面位置 删除多余的控件,只保留如下 修改title为TCPAssistant. 二.界面设计 ...

  8. 用QT写一个TCP通信助手(三、TCP通信)

    一.说明 首先我们先分析一下: 由于不支持多继承,所以比MFC稍微麻烦了一点,但是QT又具有它自身的优势,那就是信号和槽,我们不用开线程去监听一些事件的触发,会方便许多. 二. 创建一个TCP类 这个 ...

  9. 基于Qt实现的TCP端口数据转发服务器

    对于Qt,比较喜欢qt的sdk框架,我也是用于做一些工作中用到的工具软件,基于qt的sdk做起来也比较快: 一.概述 今天要说的这个tcp端口转发服务器,主要是用于将监听端口的数据转发到另外一个服务器 ...

最新文章

  1. 4G EPS 的网络协议栈
  2. Docker 下安装 Spark
  3. 初识遗传算法 蚁群算法
  4. python浅拷贝和深拷贝
  5. 数据库中的实体、元组、字段、属性、码、分量、依赖关系、完全部份传递依赖、范式等你了解吗?【笔记自用】
  6. 学习汇编图文. 寄存器的特殊用法
  7. linux基础-0.0绝对路径与相对路径
  8. React 15.5带来重大修改
  9. 关于DataFormWebPart中CreatedModifiedInfo信息的分开使用
  10. 提交App中断出现 Cannot proceed with delivery an existing transporter instan
  11. 理解Android编译命令
  12. NOD32 V5 企业版部署方案
  13. usbcan、can分析仪的产品特点和功能特点
  14. 北航机试 16逆序数
  15. ios push上移64_iOS上的C64 Basic
  16. Python 3个小练习
  17. linux内核 超线程设置,linux – 为什么在启用超线程后性能会变差?
  18. 致远OA漏洞学习——A6版本敏感信息泄漏漏洞
  19. EBS 使用API更新物料属性 Inv_Item_Grp
  20. 微信小程序背景图真机显示不了

热门文章

  1. Codeforces 378C
  2. 【笑一笑,十年少】【囧一囧,眼神好】
  3. 简单用户登录系统 实现注册 登录功能
  4. 无辜被黑 我在北大青鸟的真实工作经历(转)
  5. DataFrame中将空字符串替换为NaN
  6. 昆仑天工AIGC——基于Stable Diffusion的多语言AI作画大模型测评
  7. cam、ts、tc、scr等电影版本标识的解析及区别(中英文对照版)
  8. 机器学习的数学基础(贰)
  9. [人工智能-深度学习-59]:生成对抗网络GAN - 基本原理(图解、详解、通俗易懂)
  10. PDF编辑搞不定?迅读PDF大师,了解一下?