Qt 网络编程QTcpSocket客户端

风陵南·2025-02-20 11:22·10 次阅读

Qt 网络编程QTcpSocket客户端

QTcpSocket

Qt的QTcpSocket是用于实现TCP客户端或服务端通信的核心类,属于Qt Network模块。它基于事件驱动的异步机制,通过信号和槽实现高效的非阻塞网络通信。

继承自QAbstractSocket,提供以下核心功能:

  • 建立/断开与TCP服务器的连接
  • 异步发送和接收数据
  • 错误检测与连接状态管理
  • 信号槽机制驱动的事件处理

核心操作流程#

创建对象与基础配置#

Copy
#include <QTcpSocket>
// 创建 socket 对象
QTcpSocket *socket = new QTcpSocket(parent);
// 设置连接超时(可选)
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); // 禁用 Nagle 算法

连接服务器#

Copy
// 异步连接(推荐)
socket->connectToHost("127.0.0.1", 12345);

发送数据#

Copy
// 发送二进制数据
QByteArray data = "Hello Server!";
socket->write(data);
// 发送文本(明确编码)
QString text = "你好,服务器!";
socket->write(text.toUtf8()); // UTF-8 编码

接收数据#

Copy
// 通过 readyRead 信号异步读取
connect(socket, &QTcpSocket::readyRead, [=]() {
while (socket->bytesAvailable() > 0) {
QByteArray data = socket->readAll();
qDebug() << "Received:" << data;
}
});

断开连接#

Copy
// 主动断开
socket->disconnectFromHost();
// 断开后自动清理释放
connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);

关键信号与状态管理#

信号 触发条件
connected() 成功建立连接
disconnected() 连接断开
readyRead() 有数据可读
errorOccurred(QAbstractSocket::SocketError) 发生错误
stateChanged(QAbstractSocket::SocketState) 连接状态变化

完整示例#

客户端#

完整代码:
Github:Qt网络编程客户端代码
部分代码:

Copy
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setLayout(ui->mainLayout);
socket = new QTcpSocket(this);
ui->pushButton_close->setDisabled(true);
connect(socket, &QTcpSocket::connected, this, [=](){
ui->textEdit_info->append("success connect to " + ip.toString() +", port: " + ui->lineEdit_port->text());
QMessageBox::information(nullptr, "成功!", "连接成功");
});
connect(socket, &QTcpSocket::errorOccurred, [](QAbstractSocket::SocketError error) {
QMessageBox::information(nullptr, "连接失败", "连接失败!");
qDebug() << "连接失败:" << error;
});
connect(socket, &QTcpSocket::readyRead, this, [=](){
QByteArray mes = socket->readAll();
QString readData = QString::fromUtf8(mes);
ui->textEdit_info->append("receive: " + readData);
});
// 已连接才启用断开按钮
connect(socket, &QTcpSocket::stateChanged, this, [=](){
if(socket->state() == QTcpSocket::ConnectedState)
ui->pushButton_close->setDisabled(false);
else
ui->pushButton_close->setDisabled(true);
});
}
Widget::~Widget()
{
delete ui;
if(socket->isValid()){
socket->disconnect();
}
}
void Widget::on_pushButton_send_clicked()
{
mes = ui->lineEdit_messsage->text();
if(socket->state() == QAbstractSocket::ConnectedState){
socket->write(mes.toStdString().c_str());
ui->textEdit_info->append("send: " + mes);
ui->lineEdit_messsage->clear();
}else{
QMessageBox::warning(nullptr, "警告", "请先连接服务器");
}
}
void Widget::on_pushButton_connect_clicked()
{
ip = QHostAddress(ui->lineEdit_IpAddress->text());
port = ui->lineEdit_port->text().toInt();
if(socket->state() != QAbstractSocket::ConnectedState)
socket->connectToHost(ip, port);
}
void Widget::on_pushButton_close_clicked()
{
if(socket->state() == QTcpSocket::ConnectedState){
socket->disconnectFromHost();
ui->textEdit_info->append("Disconnect from " + ip.toString());
}
}

服务端#

完整代码:
Github:Qt网络编程服务端代码
部分代码:

Copy
void Widget::on_pushButton_listen_clicked()
{
// 开始监听
int port = ui->lineEdit_port->text().toInt();
QHostAddress ip;
if(ui->comboBox_ip->currentIndex() == 0)
ip = QHostAddress::Any;
else
ip = QHostAddress(ui->comboBox->currentText());
if(!server->listen(ip, port)){
qDebug() << "listen Error!";
return;
}
// qDebug() << "Server listening on port " + ui->lineEdit_port->text();
ui->textEdit_info->append("Server listening on port " + ui->lineEdit_port->text());
connect(server, &QTcpServer::newConnection, this, &Widget::handleNewConnection);
ui->pushButton_listen->setDisabled(true);
ui->pushButton_stop_listen->setDisabled(false);
}
void Widget::handleNewConnection()
{
// 更新在线人数
QString onlineNum = QString::fromStdString(
std::to_string(server->findChildren<QTcpSocket*>().size()));
ui->label_onlineNum->setText(onlineNum);
QTcpSocket *currentClient = server->nextPendingConnection();
clients.append(currentClient);
ui->textEdit_info->append("new connection form :" + currentClient->localAddress().toString());
// 读取客户端传来的数据
connect(currentClient, &QTcpSocket::readyRead, [=](){ handleReadData(currentClient); });
// 断开连接后 移除Socket释放内存
connect(currentClient, &QTcpSocket::disconnected, [=](){ handleDisconnect(currentClient); });
}
void Widget::handleReadData(QTcpSocket* client)
{
QByteArray data = client->readAll();
QString utf8Text = QString::fromUtf8(data);
ui->textEdit_info->append("receive: " + utf8Text);
qDebug() << "message:" << utf8Text;
}
void Widget::on_pushButton_send_clicked()
{
QString mes = ui->textEdit_sendData->toPlainText();
// 广播发送给连接的所有客户端
if(clients.size() == 0){
QMessageBox::warning(nullptr, "无连接", "没有客户端连接到服务器");
return;
}
for(auto client : clients){
if(client->state() == QAbstractSocket::ConnectedState){
client->write(mes.toStdString().c_str());
}
}
ui->textEdit_info->append("send: " + mes);
ui->textEdit_sendData->clear();
}
void Widget::on_pushButton_stop_listen_clicked()
{
if(server->isListening()){
// 断开连接槽函数
disconnect(server, &QTcpServer::newConnection, this, &Widget::handleNewConnection);
// 停止监听(停止接收新的连接)
server->close();
ui->pushButton_stop_listen->setDisabled(true);
ui->pushButton_listen->setDisabled(false);
// 强制断开所有已连接的客户端
for (QTcpSocket *client : clients) {
client->disconnectFromHost();
client->deleteLater();
}
ui->textEdit_info->append("server closed...");
}
}
posted @   风陵南  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示
目录