目录
1.基本概念
2.QTcpServer
2.1 常用接口
2.2信号
3 QTcpSocket
3.1构造函数
3.2 连接函数
3.3 接收数据
3.4 发送数据
3.5 信号
4.通信的过程
4.1服务器端
4.2 客户端
通信流程:
1.基本概念
QT是 C++ 的一个框架,并且里边提供了用于套接字通信的类(TCP、UDP);
使用 Qt 提供的类进行基于 TCP 的套接字通信需要用到两个类:
- QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。
- QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。
这两个套接字通信类都属于网络模块 network
2.QTcpServer
2.1 常用接口
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 表示随机绑定一个可用端口。
- 返回值:绑定成功返回 true,失败返回 false
2.2信号
//当接收新连接导致错误 会发出的acceptError信号
[signal] void QTcpServer::acceptError(QAbstractSocket::SocketError socketError);
//当有新连接可用的时候会发出newConnection信号
[signal] void QTcpServer::newConnection();
3 QTcpSocket
QTcpSocket 是一个套接字通信类,不管是客户端还是服务器端都需要使用。在 Qt 中发送和接收数据也属于 IO 操作(网络 IO).
3.1构造函数
QTcpSocket::QTcpSocket(QObject *parent = Q_NULLPTR);
3.2 连接函数
[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);
参数:
- hostName:字符形式的 IP地址
- address :QHostAddress类型 的ip地址 对象
- port:端口号
3.3 接收数据
在QT框架中,都会维护一个读缓冲区和 写缓冲区,读操作是直接从 QT维护的 读缓冲区 和 写缓冲区直接读取。
// 指定可接收的最大字节数 maxSize 的数据到指针 data 指向的内存中
qint64 QIODevice::read(char *data, qint64 maxSize);
// 指定可接收的最大字节数 maxSize,返回接收的字符串
QByteArray QIODevice::read(qint64 maxSize);
// 将当前可用操作数据全部读出,通过返回值返回读出的字符串
QByteArray QIODevice::readAll();
3.4 发送数据
// 发送指针 data 指向的内存中的 maxSize 个字节的数据
qint64 QIODevice::write(const char *data, qint64 maxSize);
// 发送指针 data 指向的内存中的数据,字符串以 \0 作为结束标记
qint64 QIODevice::write(const char *data);
// 发送参数指定的字符串
qint64 QIODevice::write(const QByteArray &byteArray);
3.5 信号
//当QTcpSocket通信的过程,数据到达时,则发出readyRead()信号
[signal] void QIODevice::readyRead();
//调用 connectToHost() 函数并成功建立连接之后发出 connected() 信号。
[signal] void QAbstractSocket::connected();
//在套接字断开连接时发出 disconnected() 信号。
[signal] void QAbstractSocket::disconnected();
4.通信的过程
4.1服务器端
- 创建套接字服务器 QTcpServer 对象
- 通过 QTcpServer 对象设置监听,即:QTcpServer::listen()
- 基于 QTcpServer::newConnection() 信号检测是否有新的客户端连接
- 如果有新的客户端连接调用 QTcpSocket *QTcpServer::nextPendingConnection() 得到通信的套接字对象
- 使用通信的套接字对象 QTcpSocket 和客户端进行通信
实例:
服务器功能:
- 点击“ 启动服务器按钮 ”,服务器开始监听
- 当有客户端连接服务器,则会在消息框中提示“成功与客户端” 建立连接
- 连接成功后,在输入框中输入消息,点击 发送按钮,会将数据发送给客户端
1.服务器的ui界面。
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 = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_send_button_clicked();
private:
Ui::MainWindow *ui;
QTcpServer* m_server;
QTcpSocket* m_socket;
};
#endif // MAINWINDOW_H
QMainWindow.cpp文件:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_server=new QTcpServer(this);
ui->port_line->setText("8081");
//建立服务器与信号的连接
connect(m_server,&QTcpServer::newConnection,this,[=](){
//获取新连接
m_socket=m_server->nextPendingConnection();
ui->his_text->append("成功与客户端建立连接....");
connect(m_socket,&QIODevice::readyRead,this,[=](){
QString s=m_socket->readAll();
ui->his_text->append("客户端:"+s);
});
connect(m_socket,&QAbstractSocket::disconnected,this,[=](){
// 断开连接
ui->his_text->append("断开连接");
//删除
m_socket->deleteLater();
});
});
}
MainWindow::~MainWindow()
{
delete ui;
}
//启动服务器的按钮
void MainWindow::on_pushButton_clicked()
{
unsigned short port=ui->port_line->text().toUShort();
//服务器开始监听
m_server->listen(QHostAddress::Any,port);
//启动按钮不被使用
ui->pushButton->setEnabled(false);
}
void MainWindow::on_send_button_clicked()
{
//获取文本框中的 发送消息
QString s=ui->send_text->toPlainText();
ui->send_text->clear();//清空消息框的数据
m_socket->write(s.toUtf8());// toUtf8 将QString 转换为 QByteArray类型
ui->his_text->append("服务器:"+ s);
}
4.2 客户端
通信流程:
- 创建通信的套接字类 QTcpSocket 对象
- 使用服务器端绑定的 IP 和端口连接服务器 QAbstractSocket::connectToHost()
- 使用 QTcpSocket 对象和服务器进行通信
实例:
客户端的功能:
- 输入端口号,ip地址,点击连接服务器,与服务器进行连接,并提示“ 连接成功”
- 点击断开连接按钮,与服务器断开连接,并提示“断开连接”
- 在输入框中输入消息,点击 发送按钮,会将数据发送给客户端
客户端的窗口界面如下图所示:
1.客户端与
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 = nullptr);
~MainWindow();
private slots:
void on_link_bt_clicked();
void on_send_button_2_clicked();
void on_close_bt_clicked();
private:
Ui::MainWindow *ui;
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);
socket=new QTcpSocket(this);
ui->close_bt->setDisabled(false);
connect(socket,&QTcpSocket::readyRead,this,[=](){
//有数据可以读取时
//读取缓冲区的数据,将数据放到消息框中
QString s=socket->readAll();
ui->his_text_2->append("服务器:"+s);
});
}
MainWindow::~MainWindow()
{
delete ui;
}
//连接按钮的槽函数
void MainWindow::on_link_bt_clicked()
{
QString ip=ui->ip_text->text();
unsigned short port=ui->port_line_2->text().toUShort();
//连接服务器
socket->connectToHost(ip,port);
ui->his_text_2->append("连接服务器成功");
ui->link_bt->setDisabled(false);
ui->close_bt->setDisabled(true);
}
//发送消息的槽函数
void MainWindow::on_send_button_2_clicked()
{
//点击发送按钮
//将输入框中的数据发送给服务器
//获取输入框中的数据
QString s=ui->send_text_2->toPlainText();
ui->send_text_2->clear(); //清空发送框中的数据
socket->write(s.toUtf8());
ui->his_text_2->append("客户端:"+s);
}
void MainWindow::on_close_bt_clicked()
{
//关闭连接
socket->close();
ui->link_bt->setDisabled(true);
}
实现效果如下: