【QT】 Qt 网络编程

一、说明

1、Qt提供TCP/UDP的套接字通信,使用时需要添加网络模块和包含对应的头文件。

①、 往项目文件中添加network模块:QT += network 。

②、 在源代码中包含有文件:#include

2、套接字的分类:

①、TCP 套接字类(QTcpSocket)

②、UDP 套接字类(QUdpSocket)

Qt服务器端设计流程(TCP)

在这里插入图片描述

linux 与 Qt 的 TCP 服务端流程对比

在这里插入图片描述

  • 在 Qt 中 listen 相当于 linux 中 bind 和 listen 两者结合在一起,是 Qt 对 linux 的更高层封装。

QTcpServer 服务器类

Header:#include
qmake:QT += network 模块
Inherits:QObject
Inherited By:QSctpServer
构造函数: 
 QTcpServer(QObject *parent = nullptr)
 
函数接口:    
//绑定并监听  
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 
QHostAddress:服务器的IP地址  
👉QHostAddress::Any 监听本地所有地址
port:端口号 
 
//接收客户端链接请求,产生新对象
QTcpSocket *QTcpServer::nextPendingConnection()
 
⚡信号: 每当有新的链接请求就会发送该信号
void newConnection() 

1.创建网络服务器对象

QTcpServer *server = new QTcpServer(this);

2.绑定并监听

bool ret  =  server->listen(QHostAddress::Any,9999);
  if(ret)
  {
      ui->statusbar->showMessage("服务器监听成功");
  }else
      {
      ui->statusbar->showMessage("服务器监听失败");
  }

3.处理客户端的链接请求

//关联新的链接请求信号
connect(server,SIGNAL(newConnection()),this,SLOT(new_connect()));
 
//槽函数 
void MainWindow::new_connect()
{
    qDebug() << "有新的客户端链接,请处理" << endl;
    //产生新对象
    QTcpSocket *clien = server->nextPendingConnection();
 
   qDebug() << "对方的IP信息:" << clien->peerAddress().toString();
   qDebug() << "对方的端口信息:" << clien->peerPort();
}

4.进行读写通信

//1.发送数据
clien->write(msg.toUtf8());
 
 
//2.关联信号与槽接收数据
connect(clien,SIGNAL(readyRead()),this,SLOT(readmsg())); 
 
void MainWindow::readmsg()
{
    //读取所有网络数据
    QString msg = clien->readAll();
}

5. 示例

UI 设计

在这里插入图片描述

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtNetwork>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_start_clicked_clicked();

    void on_pushButton_send_clicked_clicked();

private:
    Ui::MainWindow *ui;
    //tcp服务器
    QTcpServer *mServer;
    QTcpSocket *mSocket;
};
#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);
}

MainWindow::~MainWindow()
{
    delete ui;
}

//启动TCP服务器
void MainWindow::on_pushButton_start_clicked_clicked()
{
    //1.构造tcp服务器对象
    mServer = new QTcpServer(this);
    //2.连接客户端连接上来的信号
    QObject::connect(mServer,&QTcpServer::newConnection,this,[&](){
        //获取客户端连接上来的套接字
        mSocket = mServer->nextPendingConnection();
        //打印客户端的地址
        QHostAddress c_addr = mSocket->peerAddress();
        ui->textBrowser->append(c_addr.toString()+"连接上来!\n");

        //使能发送输入框和按钮
        ui->lineEdit->setEnabled(true);
        ui->pushButton_send_clicked->setEnabled(true);

        //连接readyRead信号和槽
        QObject::connect(mSocket,&QTcpSocket::readyRead,this,[&](){
            //接收数据
            QByteArray arr = mSocket->readAll();
            //转换成字符串显示
            ui->textBrowser->append("rcv:"+QString(arr)+"\n");
        });
    });
    //3.监听
    mServer->listen(QHostAddress::Any,ui->spinBox->value());

    //连接回车发送的信号和槽
    QObject::connect(ui->lineEdit, &QLineEdit::returnPressed, this, &MainWindow::on_pushButton_send_clicked_clicked);


    //禁止端口号和启动按钮
    ui->spinBox->setEnabled(false);
    ui->pushButton_start_clicked->setEnabled(false);
}


//发送
void MainWindow::on_pushButton_send_clicked_clicked()
{
    //获取发送的数据
    QString str = ui->lineEdit->text();
    //转换成QByteArray
    QByteArray arr;
    arr.append(str);

    //发送
    mSocket->write(arr);
    //显示发送的内容
    ui->textBrowser->insertPlainText("send:"+str+"\n");
    //清空lineEdit
    ui->lineEdit->clear();
}

在这里插入图片描述

Qt 客户端设计流程(TCP)

在这里插入图片描述

QTcpSocket 客户端类

Header:#include
qmake:QT += network 💥.pro记得加模块
Inherits:QAbstractSocket
Inherited By:QSctpSocket and QSslSocket
构造函数: 
QTcpSocket(QObject *parent = nullptr) 
 
函数接口: 
connectToHost(const QHostAddress &, quint16)  //链接服务器 
QHostAddress:服务器IP地址
quint16     :服务器端口号
 
//读取操作 
read(char *, qint64 )   
char *:  读取数据的存储地址 
qint64:  读取数据的大小 
QByteArray read(qint64 maxSize) //读取数据并返回字节数组  
QByteArray readAll()             //读取所有数据并返回字节数组
 
//写操作 
qint64 write(const QByteArray &byteArray)  //写入字节数组 
qint64 write(const char *data)  //写入字符串
qint64 write(const char *data, qint64 maxSize) //写入字符串并设置大小为 maxSize
 
//关闭通信
void close()

1.创建网络通信对象

 //1.创建网络socket 
QTcpSocket *clien = new   QTcpSocket(this);

2.链接服务器

//链接IP为 "192.168.73.1" 端口为 8888 的服务器
 clien->connectToHost("192.168.73.1",8888);

3.write 发送数据

qint64 write(const QByteArray &byteArray)  //写入字节数组 
qint64 write(const char *data)  //写入字符串
qint64 write(const char *data, qint64 maxSize) //写入字符串并设置大小为 maxSize
 
 
//发送数据例子  
clien->write("hello");
clien->write("1234567",2);
 
QString msg = "哈哈哈";
clien->write(msg.toUtf8());

4.😱(难点)read 接收数据

在QT中所有的阻塞IO接口,都是使用信号与槽解决的! 每当阻塞IO有数据时,系统就会发送相对应的信号。 
[signal] void QIODevice::readyRead() 有数据可读信号! 只要关联该信号,处理数据即可! 
 
-------读取数据例子-------
 connect(clien,&QTcpSocket::readyRead,this,[&](){
       //读取所有网络数据
        QString msg = clien->readAll();
 
        qDebug() << msg;
   });

QUdpSocket 类

Header:#include
qmake:QT += network模块
Inherits:QAbstractSocket
//构造函数
QUdpSocket(QObject *parent = nullptr)
 
//函数接口
qint64 writeDatagram (const char *data,   //数据的缓存区 
 qint64 size,        //发送数据的大小
 const QHostAddress &address, //接收端的IP地址 
 quint16 port)			//接收端端口
 
qint64 readDatagram(char *data, //数据的缓存地址
qint64 maxSize, //接收数据大小
QHostAddress *address = nullptr,  //对方的IP地址信息
quint16 *port = nullptr)   //对方的端口信息 
 
//读取数据包并返回数据包类 
QNetworkDatagram receiveDatagram(qint64 maxSize = -1) 
//判断是否有数据报可读
bool QUdpSocket::hasPendingDatagrams() const
 
 
QT——》IP地址类QHostAddress 
 QHostAddress(const QString &address)  //字符串转换为IP地址类  
 
 转换例子👉 QHostAddress("192.168.73.1")

UDP发送端

在这里插入图片描述

1.创建UDP对象

QUdpSocket *udp_send= new QUdpSocket(this);

2.发送UDP数据报

//2.发送一个UDP数据报 
udp_send->writeDatagram("hello",5,QHostAddress("192.168.73.1"),8888);

UDP 接收端

在这里插入图片描述

1.创建UDP对象

QUdpSocket *udp_recv = new QUdpSocket(this);

2.绑定接收端地址信息

if(udp_recv->bind(QHostAddress::Any,8888))
{
    ui->statusbar->showMessage("绑定成功");
}else
{
     ui->statusbar->showMessage("绑定失败");
}

3.读取数据

信号:当有数据来临时,就会发送该信号
void readyRead() ;
 
connect(udp_recv,&QUdpSocket::readyRead,this,[&](){
   char  buf[1024]={0};
   udp_recv->readDatagram(buf,1024,NULL,NULL);
   qDebug() <<  buf;
});
 
-----------------------------------------------------------------
QNetworkDatagram  数据报类
  
QByteArray data() const  //数据  
   
QHostAddress senderAddress() const //发送者地址  
int senderPort() const    //发送者端口 
 
 
//3.关联信号与槽 
connect(udp_recv, &QUdpSocket::readyRead,this, &MainWindow::readPendingDatagrams); 



//读取数据报槽函数 
void MainWindow::readPendingDatagrams() 
{ 
    while (udp_recv->hasPendingDatagrams()) { 
        QNetworkDatagram datagram = udp_recv->receiveDatagram(); 
 
         //转换数据报获取数据 
         QString  ip  = datagram.senderAddress().toString(); 
         int port     = datagram.senderPort(); 
         QString msg  = datagram.data(); 
 
        ui->textBrowser->append(QString("%1 %2 %3").arg(ip).arg(port).arg(msg)); 
 
    } 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值