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!"
这表明服务器成功接收了来自客户端的消息