Qt网络通信

1. UDP通信

1.1 udp通信的基本流程

创建套接字

绑定套接字

进行通信

关闭套接字

涉及到的类和信号

QUdpSocket:Udp套接字类,类对象就是一个udp套接字对象
QHostAddress:ip地址类
void readyRead():信号,当有数据到达可读,就会产生这个信号

1.2 举例

通信端1

udp1

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

    //当有数据到达时的槽
    void readdate();
private:
    Ui::Widget *ui;

    //创建udp对象
    QUdpSocket* socket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

//udp通信
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1. 创建udp套接字
    socket = new QUdpSocket;

    //2. 绑定
    //ip地址类,直接构造设置ip地址
    QHostAddress addr("192.168.124.33");
    //addr.setAddress();//函数设置ip地址
    socket->bind(addr,10000);


    //绑定readyRead信号,当有数据到达时,就会触发信号,去接收数据
    connect(socket,SIGNAL(readyRead()),this,SLOT(readdate()));

}

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

//发送数据
void Widget::on_pushButton_clicked()
{
    //发送数据
    //定义缓冲区
    QByteArray data = ui->textEdit_2->toPlainText().toLocal8Bit();//toLocal8Bit()将数据转换为QByteArray类型
    socket->writeDatagram(data,QHostAddress("192.168.124.33"),10001);
}

//接收数据
void Widget::readdate(){

    //定义缓冲区
    QByteArray data;
    data.resize(1024);

    //读发来的数据存,储到data中
    QHostAddress addr;
    quint16 port;
    //size是收到的数据大小
    int size = socket->readDatagram(data.data(),data.size(),&addr,&port);//参数addrr,port是发送方的ip和端口

    data.resize(size);

    //展示数据
    ui->textEdit->append("发送端的ip:"+addr.toString()+"  port:"+QString::number(port));
    ui->textEdit->append(data);
}


通信端2

udp2

widget.h

widget.cpp

运行

2. TCP通信

2.1 客户端通信流程 QTcpSocket

1. 创建套接字

2. 绑定套接字

3. 连接服务器

4. 进行通信

5. 关闭套接字

2.1.1 涉及的信号 

connected():信号,当连接服务器且连接成功

readyRead():信号,当发送给数据到套接字,套接字可读

disconnected():信号,只要套接字断开连接,就会产生

2.2 服务端通信流程 QTcpServer

1. 创建套接字

2绑定套接字

3监听套接字---套接字类型改变改为监听套接字

4连接客户端---得到与客户端进行通信的套接字

5进行通信

6关闭套接字

相关函数

nextPendingConnection():服务器建立与客户端连接,返回值 QTcpScket 类对象:通信套接字对象

2.2.1 涉及的信号

newConnection():信号,当有新的客户端连接时,会产生这个信号

readyRead():信号,当发送给数据到套接字,套接字可读

disconnected():信号,只要套接字断开连接,就会产生

2.2 举例:模拟客户端和服务端通信

2.2.1 客户端

tcp_client

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_connect_clicked();

    //当连接服务器,且连接成功的槽
    void socket_conn();

    void on_pushButton_send_clicked();

    //当有数据发来时,触发该信号
    void readdata();

    void on_pushButton_duankai_clicked();

    //当连接断开,触发该信号
    void socket_disconn();

private:
    Ui::Widget *ui;

    //创建tcp对象
    QTcpSocket* socket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"


//tcp通信客户端
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.创建套接字对象
    socket = new QTcpSocket;

    //2.绑定,这里其实可以不用绑定,系统会自动给你分配
    socket->bind(QHostAddress("192.168.124.33"),9999);

    //设置连接按钮可点击,发送和点击不可点
    ui->pushButton_connect->setEnabled(true);
    ui->pushButton_send->setEnabled(false);
    ui->pushButton_duankai->setEnabled(false);

}

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


//连接服务器
void Widget::on_pushButton_connect_clicked()
{
    //3. 连接服务器,参数1服务端ip,参数2服务端端口
    socket->connectToHost(ui->lineEdit_ip->text(),ui->lineEdit_port->text().toUShort());//toUShort() 字符串转为数字


    //提示,注意这里的信号和槽的绑定写在连接按钮里,后面会有个问题,就是每连接一次信号和槽都会再绑定一次,造成多次重复绑定
    //要解决问题,就需要在断开连接哪里把绑定的信号和槽断开
    //如果把信号和槽的绑定写在上面的构造里就不会有这个问题了
    
    //当连接服务器,且连接成功,就会触发该信号
    connect(socket,SIGNAL(connected()),this,SLOT(socket_conn()));

    //当有数据发来时,触发该信号
    connect(socket,SIGNAL(readyRead()),this,SLOT(readdata()));

    //当连接断开,触发该信号
    connect(socket,SIGNAL(disconnected()),this,SLOT(socket_disconn()));
}

//当连接服务器,且连接成功,触发的信号对应的槽
void Widget::socket_conn(){
    //接收框里提示连接成功
    ui->textEdit_receice->append(ui->lineEdit_ip->text()+":"+ui->lineEdit_port->text()+"  connect ok");

    //设置连接按钮不可点击,断开和发送可点击
    ui->pushButton_connect->setEnabled(false);
    ui->pushButton_send->setEnabled(true);
    ui->pushButton_duankai->setEnabled(true);
}


//点击发送数据给服务器
void Widget::on_pushButton_send_clicked()
{
    //4.将数据发送给服务器
    //toStdString().c_str()先转为c++标准字符串,再转为c字符串
    socket->write(ui->textEdit_write->toPlainText().toStdString().c_str());

}

//当有数据发来时,接收数据
void Widget::readdata(){
    //5.读取数据
    QByteArray data =  socket->readAll();
    ui->textEdit_receice->append(data);
}


//客户端断开与服务器的连接
void Widget::on_pushButton_duankai_clicked()
{
    //6.断开与服务端的连接
    socket->disconnectFromHost();

}

//连接断开后要做到处理  对应的槽(只要连接断开就会进入这个槽函数)
void Widget::socket_disconn(){
    //接收框里提示连接断开
    ui->textEdit_receice->append(ui->lineEdit_ip->text()+":"+ui->lineEdit_port->text()+"  disconnect");

    //把绑定的信号和槽断开
    disconnect(socket,SIGNAL(connected()),this,SLOT(socket_conn()));
    disconnect(socket,SIGNAL(readyRead()),this,SLOT(readdata()));
    disconnect(socket,SIGNAL(disconnected()),this,SLOT(socket_disconn()));

    //设置连接按钮可点击,发送和点击不可点
    ui->pushButton_connect->setEnabled(true);
    ui->pushButton_send->setEnabled(false);
    ui->pushButton_duankai->setEnabled(false);
}

测试使用网络调试助手E:\peixunqianrushi_ziliao\网络调试助手

连接

发送数据

点击断开连接

2.2.2 服务端

服务器设置为多线程---并发服务器,每个客户端在线程中进行操作

tcp_server

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <thread_tcp.h>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_start_clicked();

    //当有新的客户端连接时的槽
    void new_conn_arrive();

    void on_pushButton_end_clicked();

private:
    Ui::Widget *ui;

    //实例化tcp对象
    QTcpServer* server;

    //存储的socket就是与客户端的通信套接字
    QTcpSocket* socket1;

    //存储所有的通信套接字
    QList<QTcpSocket*> list;

};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"


//tcp通信服务端
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.创建tcp服务端套接字
    server = new QTcpServer;

    //2.绑定,这里提示,在qt中绑定和监听写在一起了,都在listen函数中

    //当有新的客户端连接时,就会触发该信号
    connect(server,SIGNAL(newConnection()),this,SLOT(new_conn_arrive()));

}

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


//启动服务器
void Widget::on_pushButton_start_clicked()
{
    //3.监听,这里提示,在qt中绑定和监听写在一起了
    server->listen(QHostAddress("192.168.124.33"),8888);
    ui->textEdit->append("服务器启动成功~~~");

}


//当有新的客户端连接请求时,触发该信号对应的槽函数
//建立连接
void Widget::new_conn_arrive(){

    //4.服务器建立与客户端的连接
    //现在的socket1就是与客户端的通信套接字
    socket1 = server->nextPendingConnection();
    //提示客户端连接成功
    socket1->write("connect success~~~~~~~");
    //将通信套接字添加进链表
    list.append(socket1);


    //从这里使用线程
    //把与客户端通信的套接字,放入线程中,使用线程来操作套接字与客户端通信
    //创建线程,有一个客户端就创建一个线程
    thread_tcp* tcp = new thread_tcp;
    //把通信套接字给线程
    tcp->socket = socket1;

    //当客户端发来消息,就会触发 在线程中的 写的槽函数,去读取客户端消息
    connect(tcp->socket,SIGNAL(readyRead()),tcp,SLOT(readdata()));

    //客户端断开连接,触发信号调用 线程中的槽,使线程关闭
    connect(tcp->socket,SIGNAL(disconnected()),tcp,SLOT(dis_conn()));


    //启动线程
    tcp->start();

}


//关闭服务器
void Widget::on_pushButton_end_clicked()
{
    for(int i=0;i<list.size();i++){
        //服务端关闭通信套接字的连接
        list.at(i)->disconnectFromHost();
    }

    list.clear();

    //关闭监听
    server->close();

    ui->textEdit->append("服务端已经关闭连接~~~~~~~");
}


thread_tcp.h

#ifndef THREAD_TCP_H
#define THREAD_TCP_H

#include <QThread>
#include <QTcpSocket>
#include <QDebug>

class thread_tcp : public QThread
{
    Q_OBJECT
public:
    thread_tcp();

    //socket就是与客户端的通信套接字
    QTcpSocket* socket;

    //执行线程的run
    void run();


public slots:
    //当客户端发来消息的槽
    void readdata();

    //只要客户端断开,就关闭线程
    void dis_conn();

};

#endif // THREAD_TCP_H

thread_tcp.cpp

#include "thread_tcp.h"

thread_tcp::thread_tcp()
{

}

//当客户端发来消息,读数据
void thread_tcp::readdata(){

    //读出数据
    QByteArray data = socket->readAll();

    //给客户端返回数据
    socket->write(data);

}

//一直执行线程
void thread_tcp::run(){
    qDebug()<<"线程执行";
    //阻塞执行
    exec();
}

//客户端断开连接时,关闭线程
void thread_tcp::dis_conn(){
    qDebug()<<"线程关闭";
    exit(0);
}

测试

运行服务端

启动客户端和网络调试助手,分别充当两个客户

分别连接,成功

发送数据,成功

分别断开连接,成功

再次分别连接,测试服务端关闭功能

关闭成功

  • 23
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt是一个跨平台的C++开发框架,提供了丰富的库和工具,可以用于开发各种类型的应用程序,包括UDP通信UDP通信是一种不可靠的传输协议,主要用于在网络上快速发送数据包,但不能确保数据包的可靠传输和顺序。Qt提供了QUdpSocket类,可以用于实现UDP通信。 QUdpSocket是一个用于UDP通信的套接字类。通过它,我们可以创建和管理UDP套接字,发送和接收UDP数据包。QUdpSocket提供了丰富的方法,如bind()用于绑定IP地址和端口号、writeDatagram()用于发送数据包、readyRead信号与hasPendingDatagrams()方法用于接收数据包等。 如果您想使用Qt实现UDP通信的猫源码,可以按照以下步骤进行: 1. 创建一个Qt项目,并添加QUdpSocket类的头文件。 2. 在主函数中创建QUdpSocket对象。 3. 使用bind()方法绑定本地的IP地址和端口号。 4. 使用writeDatagram()方法发送数据包。 5. 使用readyRead信号与hasPendingDatagrams()方法接收数据包,并处理接收到的数据。 在编写源码时,您可以根据需求添加其他功能,如数据包拆分和组装、数据包的校验等。此外,还可以根据实际情况处理数据丢失和顺序错乱的问题。 总之,使用Qt的QUdpSocket类可以很方便地实现UDP通信。通过自定义的猫源码,您可以实现基于UDP的猫通信程序,用于在网络上传输猫的信息。希望对您有所帮助! ### 回答2: Qt是一种跨平台的C++框架,可以用于开发图形化界面和网络通信等应用。而UDP(User Datagram Protocol)是一种无连接的传输协议,无需建立连接就可以发送数据,适用于实时性要求较高的通信场景。 Qt提供了丰富的网络编程支持,其中包括UDP通信QtUDP通信猫源码是一个示例项目,用于展示如何使用Qt框架进行UDP通信的实现。 在这个源码中,首先需要创建一个QUdpSocket对象,用于发送和接收UDP数据包。通过调用QUdpSocket的bind()函数,可以将socket绑定到指定的IP地址和端口上。 接下来,可以通过调用QUdpSocket的writeDatagram()函数来发送UDP数据包。该函数需要指定目标IP地址和端口,以及待发送的数据。如果发送成功,writeDatagram()函数将返回实际发送的数据字节数。 同时,可以通过重写QUdpSocket的readyRead()信号的槽函数,来实现数据的接收与处理。当有数据到达时,系统将自动发出readyRead()信号,可以通过连接信号与槽函数的方式,将数据接收和处理的逻辑代码写入槽函数中。 该示例项目通常会实现一个简单的UDP聊天室功能,即用户可以发送消息到指定的IP地址和端口,并接收其他用户发送的消息。通过解析接收到的数据包,可以将发送方的IP地址和消息内容进行显示。 总之,Qt UDP通信猫源码是一个展示如何使用Qt框架进行UDP通信的示例项目,可以通过该源码了解UDP通信的基本原理和代码实现。如果需要在自己的项目中使用UDP进行通信,可以参考该源码进行调整和拓展。 ### 回答3: Qt是一种跨平台的C++框架,可用于开发各种类型的应用程序。UDP(User Datagram Protocol)是一种无连接的网络传输协议,它可以在网络上发送和接收数据包,但不保证数据包的可靠传输。通信猫源码是指使用Qt开发的一种UDP通信应用程序的源代码。 UDP通信猫源码可以用于实现基于UDP协议的网络通信功能。在该源码中,通信猫可以作为服务器或客户端的角色来进行通信。作为服务器,通信猫可以监听指定的端口,接收来自客户端发送的数据包,并对数据进行处理。作为客户端,通信猫可以向指定的服务器IP地址和端口发送数据包。 通信猫源码通常包含了UDP通信相关的功能和逻辑,例如创建UDP套接字、绑定端口、发送和接收数据包等。该源码还可能包含与界面相关的代码,以便用户能够通过界面与通信猫进行交互。 使用通信猫源码,开发者可以快速实现UDP通信功能,并根据自己的需求进行定制和扩展。例如,可以基于该源码进行进一步的开发,添加数据校验、加密、压缩等功能,以提高通信的可靠性和安全性。 总之,Qt UDP通信猫源码提供了一个基于UDP协议的通信解决方案的基础代码,开发者可以在此基础上进行二次开发,以满足自己的特定需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值