Qt 的网络通信(TCP)
基于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
参数:
- address: 通过类 QHostAddress 可以封装 IPv4 、 IPv6 格式的 IP地址,QHostAddress :: Any 表示自动绑定;
- port: 端口号 , 指定为 0 表示随机绑定一个可用端口;
- 返回值: 绑定失败返回 false , 成功 true;
- 得到和客户端建立连接之后用于通信的
QTcpSocket
套接字对象,它是QTcpServer
的一个子对象,当QTcpServer
对象析构的时候会自动析构这个子对象,当然也可自己手动析构,建议用完之后自己手动析构这个通信的QTcpSocket
对象。
QTcpSocket *QTcpServer::nextPendingConnection();
- 阻塞等待客户端发起的连接请求,
不推荐在单线程程序中使用,建议使用非阻塞方式处理新连接,即使用信号 newConnection()
。
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR);
参数:
- mes: 指定阻塞的最大时间 , 单位毫秒;
- 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 服务器端
- 创建套接字服务器
QTcpServer
对象 - 通过
QTcpServer
对象设置监听,即:QTcpServer::listen()
- 基于
QTcpServer::newConnection()
信号检测是否有新的客户端连接 - 如果有新的客户端连接调用
QTcpSocket *QTcpServer::nextPendingConnection()
得到通信的套接字对象 - 使用通信的套接字对象
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 客户端
- 创建通信的套接字类
QTcpSocket
对象 - 使用服务器端绑定的 IP 和端口连接服务器
QAbstractSocket::connectToHost()
- 使用
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)相关推荐
- 03 - Qt 多线程网络通信——套接字
文章序言 日志1.0 :在QT中如何使用TCP协议进行套接字通信(即指网络通信) TCP 和 UDP是传输层协议, 二者的区别: TCP是面向连接的流式传输协议:TCP传输, 数据安全: UDP是面向 ...
- Qt中的TCP客户端编程
文章目录 1 Qt中的TCP客户端编程 1.1 TCP客户端编程介绍 1.2 QTcpSocket的同步编程 1.3 QTcpSocket的异步编程 1 Qt中的TCP客户端编程 1.1 TCP客户端 ...
- qt android 网络编程实例,QT网络编程Tcp下C/S架构的即时通信实例
先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include #include # ...
- Qt网络编程——TCP
Qt网络编程--TCP 1. 概念 2. 服务器 3. 客户端 4. TCP服务器和客户端互传文件 5. 资源下载 1. 概念 TCP(Transmission Control Protocol, 传 ...
- QT -- TcpSocket实例,使用Qt中的tcp通信协议,构建客户端和服务端,实现局域网通信软件功能
Qt中使用Tcp构建通信客户端实现聊天信息发送连接等 1.简介 2.项目创建和界面构建 1)流程图 2)项目构建 3)界面构建 3.代码设计 1)项目pro添加 2)客户端设计 a. clientwi ...
- 默蓝网络通信TCP/HTTP测试工具介绍
默蓝网络通信TCP/HTTP测试工具介绍 默蓝网络通信TCP/HTTP测试工具为广大技术开发人员提供的通信测试工具,其具备如下功能: 1.支持TCP/IP协议的网络通信,TCP服务端和客户端,可单条发 ...
- 用QT写一个TCP通信助手(一、界面设计)
一.新建工程 创建QT widgets工程 修改项目名称TCPAssistant,下一步下一步直到出现此界面位置 删除多余的控件,只保留如下 修改title为TCPAssistant. 二.界面设计 ...
- 用QT写一个TCP通信助手(三、TCP通信)
一.说明 首先我们先分析一下: 由于不支持多继承,所以比MFC稍微麻烦了一点,但是QT又具有它自身的优势,那就是信号和槽,我们不用开线程去监听一些事件的触发,会方便许多. 二. 创建一个TCP类 这个 ...
- 基于Qt实现的TCP端口数据转发服务器
对于Qt,比较喜欢qt的sdk框架,我也是用于做一些工作中用到的工具软件,基于qt的sdk做起来也比较快: 一.概述 今天要说的这个tcp端口转发服务器,主要是用于将监听端口的数据转发到另外一个服务器 ...
最新文章
- 4G EPS 的网络协议栈
- Docker 下安装 Spark
- 初识遗传算法 蚁群算法
- python浅拷贝和深拷贝
- 数据库中的实体、元组、字段、属性、码、分量、依赖关系、完全部份传递依赖、范式等你了解吗?【笔记自用】
- 学习汇编图文. 寄存器的特殊用法
- linux基础-0.0绝对路径与相对路径
- React 15.5带来重大修改
- 关于DataFormWebPart中CreatedModifiedInfo信息的分开使用
- 提交App中断出现 Cannot proceed with delivery an existing transporter instan
- 理解Android编译命令
- NOD32 V5 企业版部署方案
- usbcan、can分析仪的产品特点和功能特点
- 北航机试 16逆序数
- ios push上移64_iOS上的C64 Basic
- Python 3个小练习
- linux内核 超线程设置,linux – 为什么在启用超线程后性能会变差?
- 致远OA漏洞学习——A6版本敏感信息泄漏漏洞
- EBS 使用API更新物料属性 Inv_Item_Grp
- 微信小程序背景图真机显示不了