Qt 实现TCP通信和UDP通信

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等;

扫描二维码关注公众号,回复: 16252891 查看本文章
  • 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!"

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

猜你喜欢

转载自blog.csdn.net/qq_33867131/article/details/130323845