Qt 实现TCP通信和UDP通信_qt udpclient-程序员宅基地

技术标签: udp  Qt  qt  tcp/ip  

Qt 实现TCP通信和UDP通信

1、TCP通信

QT中实现TCP通信主要用到了以下类:QTcpServer、QTcpSocket、QHostAddress等;

  • 使用QTcpServer来创建一个TCP服务器,在新的连接建立时,将新建立连接的socket添加到列表中,以便发送数据,同时监听在指定的IP地址和端口上,并在有新的客户端连接上来时进行处理;
  • 使用QTcpSocket来创建一个TCP客户端,连接到服务器并发送数据;

示例代码:

(1)创建两个头文件(TcpServer.h 和 TcpClient.h):

TcpServer.h

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>

class TcpServer : public QObject
{
    
    Q_OBJECT
public:
    explicit TcpServer(QObject *parent = nullptr);

signals:

public slots:
    void startServer();
    void newClientConnection();
    void readData();
    void clientDisconnected();

private:
    QTcpServer *tcpServer;
    QList<QTcpSocket *> clients;
};

#endif // TCPSERVER_H

TcpClient.h

#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QObject>
#include <QTcpSocket>

class TcpClient : public QObject
{
    
    Q_OBJECT
public:
    explicit TcpClient(QObject *parent = nullptr);

public slots:
    void onConnected();
    void onDisconnected();
    void onError(QAbstractSocket::SocketError error);
    void onReadyRead();
    void connectToServer(QString ipAddress, int port);
    void sendData(QByteArray data);

private:
    QTcpSocket *socket;
};

#endif // TCPCLIENT_H

(2)创建两个源文件(TcpServer.cpp 和 TcpClient.cpp):

TcpServer.cpp

#include "tcpserver.h"
#include <QDebug>

TcpServer::TcpServer(QObject *parent) : QObject(parent)
{
    
}

void TcpServer::startServer()
{
    
    tcpServer = new QTcpServer(this);
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClientConnection()));

    if (!tcpServer->listen(QHostAddress::Any, 1234))
    {
    
        qDebug() << "Unable to start the server: " << tcpServer->errorString();
        return;
    }
    qDebug() << "Listening on " << QHostAddress::Any << ":" << "1234";
}

void TcpServer::newClientConnection()
{
    
    while (tcpServer->hasPendingConnections())
    {
    
        QTcpSocket *client = tcpServer->nextPendingConnection();
        clients.push_back(client);
        QObject::connect(client, SIGNAL(readyRead()), this, SLOT(readData()));
        QObject::connect(client, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
    }
}

void TcpServer::readData()
{
    
    QTcpSocket *sender = static_cast<QTcpSocket*>(QObject::sender());
    QByteArray data = sender->readAll();
    qDebug() << "Received: " << data;
}

void TcpServer::clientDisconnected()
{
    
    QTcpSocket *sender = static_cast<QTcpSocket*>(QObject::sender());
    clients.removeOne(sender);
    sender->deleteLater();
}

TcpClient.cpp

#include "tcpclient.h"
#include <QDebug>

TcpClient::TcpClient(QObject *parent) : QObject(parent)
{
    
}

void TcpClient::connectToServer(QString ipAddress, int port)
{
    
    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(connected()), this, SLOT(onConnected()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
    connect(socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));

    socket->connectToHost(ipAddress, port);
}

void TcpClient::sendData(QByteArray data)
{
    
    if (socket && socket->state() == QAbstractSocket::ConnectedState)
        socket->write(data);
}

void TcpClient::onConnected()
{
    
    qDebug() << "Connected!";
}

void TcpClient::onDisconnected()
{
    
    qDebug() << "Disconnected!";
}

void TcpClient::onError(QAbstractSocket::SocketError error)
{
    
    qDebug() << "Error: " << socket->errorString();
}

void TcpClient::onReadyRead()
{
    
    qDebug() << "Received: " << socket->readAll();
}

(3)TCP客户端与TCP服务端通信,打开main.cpp,添加头文件以及创建TcpServer对象和TcpClient对象:

main.cpp

#include <QCoreApplication>
#include "tcpserver.h"
#include "tcpclient.h"

int main(int argc, char *argv[])
{
    
    QCoreApplication a(argc, argv);

    //创建服务器对象
    TcpServer server;
    server.startServer();

    //创建客户端对象
    TcpClient client;
    client.connectToServer("127.0.0.1", 1234);

    //发送数据
    client.sendData("Hello from client!");

    return a.exec();
}

2、UDP通信

QT中实现UDP通信主要用到了以下类:QUdpSocket、QHostAddress等;

  • UdpServer是服务器端,用于监听客户端发送的消息并回复同样的消息;
  • UdpClient是客户端,用于向服务器发送一条消息,并等待来自服务器的回复;

示例代码:

(1)创建两个头文件(UdpServer.h 和 UdpClient.h):

UdpServer.h

UdpServer继承自QObject,该类包含私有成员变量QUdpSocket *udpSocket,start()函数用于启动服务器;

#ifndef UDPSERVER_H
#define UDPSERVER_H

# 这两个头文件分别用于QObject基类和QUdpSocket类,前者提供Qt对象模型所需的大量工具和服务,后者用于UDP套接字支持
#include <QObject>
#include <QUdpSocket>

class UdpServer : public QObject
{
    
    Q_OBJECT
public:
    explicit UdpServer(QObject *parent = nullptr);
    void start();

signals:

private:
    QUdpSocket *udpSocket;
};

#endif // UDPSERVER_H

UdpClient.h

UdpClient同样继承自QObject,包含一个QUdpSocket指针udpSocket和一个send()函数用于向服务器发送消息;

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <QObject>
#include <QUdpSocket>

class UdpClient : public QObject
{
    
    Q_OBJECT
public:
    explicit UdpClient(QObject *parent = nullptr);
    void send(const QString &message);

signals:

private:
    QUdpSocket *udpSocket;
};

#endif // UDPCLIENT_H

(2)创建两个源文件(UdpServer.cpp 和 UdpClient.cpp):

UdpServer.cpp

UdpServer的实现文件中,首先在构造函数中创建了一个QUdpSocket对象udpSocket,该对象用于通信,start()函数则用于启动服务器,包括绑定端口和建立接收数据的连接:

  • bind()函数用于将UDP套接字与IP地址和端口绑定,以便开始监听传入的消息;
  • readyRead信号是QUdpSocket类的一个信号,这里使用connect()函数将其与另一个函数连接起来,该函数会在每次接收到数据时执行;
#include "UdpServer.h"
#include <QDebug>

UdpServer::UdpServer(QObject *parent) : QObject(parent)
{
    
    udpSocket = new QUdpSocket(this);
}

void UdpServer::start()
{
    
    quint16 port = 1234;

    if (udpSocket->bind(QHostAddress::AnyIPv4, port))
    {
    
        qDebug() << "UDP server is listening on port" << port;
    }
    else
    {
    
        qDebug() << "Failed to bind the UDP server to port" << port;
    }

    connect(udpSocket, &QUdpSocket::readyRead, this, [this]()
    {
    
        while (udpSocket->hasPendingDatagrams())
        {
    
            QByteArray datagram;
            datagram.resize(udpSocket->pendingDatagramSize());
            udpSocket->readDatagram(datagram.data(), datagram.size());

            qDebug() << "Received from client:" << datagram;
        }
    });
}

UdpClient.cpp

UdpClient的实现文件中,同样在构造函数中创建了一个QUdpSocket对象udpSocket,用于通信,send()函数则用于向服务器发送消息:

  • writeDatagram()函数用于将datagram指定的数据报发送到目标地址和端口;
  • qDebug()函数用于输出日志信息,记录已发送至服务器的消息;
#include "UdpClient.h"
#include <QDebug>

UdpClient::UdpClient(QObject *parent) : QObject(parent)
{
    
    udpSocket = new QUdpSocket(this);
}

void UdpClient::send(const QString &message)
{
    
    QByteArray datagram = message.toUtf8();

    quint16 port = 1234;
    QHostAddress address("127.0.0.1");

    udpSocket->writeDatagram(datagram, address, port);

    qDebug() << "Sent to server:" << message;
}

(3)UDP客户端与UDP服务端通信,打开main.cpp,添加头文件以及创建UdpServer对象和UdpClient对象:

main.cpp

主函数主要是启动UdpServer和UdpClient,并向服务器发送一条消息:

  • udpServer和udpClient是用于运行这两个对象的实例;
  • send()函数发送了一条消息,该消息会被服务器接收并回复同样的消息;
  • a.exec()函数开始Qt事件循环,直到程序退出为止;
#include <QCoreApplication>
#include "UdpServer.h"
#include "UdpClient.h"

int main(int argc, char *argv[])
{
    
    QCoreApplication a(argc, argv);

    UdpServer udpServer;
    udpServer.start();

    UdpClient udpClient;
    udpClient.send("Hello from client!");

    return a.exec();
}

在Qt Creator中运行程序,可以看到以下输出:

UDP server is listening on port 1234
Sent to server: "Hello from client!"
Received from client: "Hello from client!"

这表明服务器成功接收了来自客户端的消息

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33867131/article/details/130323845

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法