文章目录
- [TCP 通信](#TCP 通信)
TCP 通信
QT主要通过QTcpSocket
和 QTcpServer
两个类实现服务器和客户端的TCP 通信。
QTcpSocket
是 Qt 提供的套接字类,看用于建立、管理和操作 TCP 连接。
常用方法
connectToHost(host, port)
:连接到指定服务器。disconnectFromHost()
:断开连接。write(QByteArray)
:发送数据。readAll()
:读取所有可用数据。waitForConnected(int timeout)
:等待连接成功。waitForReadyRead(int timeout)
:等待数据可读。
常用信号
connected()
:连接成功时触发。disconnected()
:连接断开时触发。readyRead()
:有新数据可读时触发。errorOccurred(QAbstractSocket::SocketError)
:发生错误时触发。
QTcpServer
是 Qt 提供的 TCP 服务器类,它主要用于监听和接受客户端连接。
常用方法
listen(QHostAddress, quint16 port)
:监听指定 IP 和端口。close()
:关闭服务器。hasPendingConnections()
:是否有新的连接请求。nextPendingConnection()
:获取新的连接对象。
常用信号
newConnection()
:有新的客户端连接时触发。
注意:要使用这两个类需要在项目文件中添加:
cpp
QT += network
下面给出一个简单示例:
https://github.com/BinaryAI-1024/QtStudy/tree/master/network/TCP
服务器监听端口 12345
,等待客户端连接。 客户端连接服务器并发送 "Hello from client!\n"
。 服务器收到消息后打印,并向客户端发送 "Hello from server!\n"
。 客户端收到服务器消息后打印。
服务器代码
cpp
// tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QObject>
class TcpServer : public QObject {
Q_OBJECT
public:
explicit TcpServer(QObject *parent = nullptr);
~TcpServer();
void startServer(quint16 port); // 启动服务器并监听指定端口
private slots:
void onNewConnection(); // 处理新的客户端连接
void onReadyRead(); // 处理客户端发送的数据
private:
QTcpServer *server; // 监听 TCP 连接的服务器对象
QTcpSocket *clientSocket; // 当前连接的客户端套接字
};
#endif // TCPSERVER_H
cpp
// tcpserver.cpp
#include "tcpserver.h"
#include <QDebug>
// 构造函数,初始化 QTcpServer 并连接 newConnection 信号
TcpServer::TcpServer(QObject *parent) : QObject(parent), server(new QTcpServer(this)) {
// // 每次有新连接可用时都会发出 newConnection() 信号
connect(server, &QTcpServer::newConnection, this, &TcpServer::onNewConnection);
}
// 析构函数,关闭服务器
TcpServer::~TcpServer() {
server->close();
}
// 启动服务器,监听指定端口
void TcpServer::startServer(quint16 port) {
if (server->listen(QHostAddress::Any, port)) {
qDebug() << "Server started on port" << port;
} else {
qDebug() << "Server failed to start!";
}
}
// 处理新客户端连接
void TcpServer::onNewConnection() {
clientSocket = server->nextPendingConnection(); // 获取新连接的客户端套接字
// 连接客户端的 readyRead 信号(有数据可读时触发)
connect(clientSocket, &QTcpSocket::readyRead, this, &TcpServer::onReadyRead);
// 连接客户端的 disconnected 信号(客户端断开连接时触发)
connect(clientSocket, &QTcpSocket::disconnected, clientSocket, &QTcpSocket::deleteLater);
qDebug() << "New client connected!";
clientSocket->write("Hello from server!\n"); // 发送欢迎消息给客户端
}
// 处理客户端发送的数据
void TcpServer::onReadyRead() {
QByteArray data = clientSocket->readAll(); // 读取客户端数据
qDebug() << "Received from client:" << data;
}
客户端代码
cpp
// tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QTcpSocket>
#include <QObject>
class TcpClient : public QObject {
Q_OBJECT
public:
explicit TcpClient(QObject *parent = nullptr);
~TcpClient();
void connectToServer(const QString &host, quint16 port); // 连接到指定服务器
private slots:
void onConnected(); // 处理成功连接到服务器的事件
void onReadyRead(); // 处理从服务器接收的数据
private:
QTcpSocket *socket; // 客户端 TCP 套接字对象
};
#endif // TCPCLIENT_H
cpp
// tcpclient.cpp
#include "tcpclient.h"
#include <QDebug>
// TcpClient 构造函数,初始化 QTcpSocket 并连接信号槽
TcpClient::TcpClient(QObject *parent) : QObject(parent), socket(new QTcpSocket(this)) {
connect(socket, &QTcpSocket::connected, this, &TcpClient::onConnected); // 连接成功信号
connect(socket, &QTcpSocket::readyRead, this, &TcpClient::onReadyRead); // 读取数据信号
}
// TcpClient 析构函数,关闭套接字
TcpClient::~TcpClient() {
socket->close();
}
// 连接到服务器的指定主机和端口
void TcpClient::connectToServer(const QString &host, quint16 port) {
socket->connectToHost(host, port);
}
// 处理成功连接到服务器的事件
void TcpClient::onConnected() {
qDebug() << "Connected to server!";
socket->write("Hello from client!\n"); // 发送消息给服务器
}
// 处理从服务器接收的数据
void TcpClient::onReadyRead() {
QByteArray data = socket->readAll();
qDebug() << "Received from server:" << data;
}
主函数
cpp
// main.cpp
#include <QCoreApplication>
#include "tcpserver.h"
#include "tcpclient.h"
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 启动服务器
TcpServer server;
server.startServer(12345);
// 启动客户端,连接到服务器
TcpClient client;
client.connectToServer("127.0.0.1", 12345);
return a.exec();
}
结果:
plaintext
Server started on port 12345
New client connected!
Connected to server!
Received from server: "Hello from server!\n"
Received from client: "Hello from client!\n"