在 Qt 框架中开发 TCP 客户端程序是网络编程的基础应用场景,本文将详细讲解如何从零开始编写一个功能完整的 TCP 客户端,实现与服务端的连接、数据发送和数据接收功能。
一、开发环境准备
- 基础环境:确保已安装 Qt 开发环境(推荐 Qt 5.12 及以上版本),包含 Qt Creator 编辑器和对应的编译套件(如 MinGW、MSVC)。
- 核心依赖 :Qt 的网络模块(
Qt Network)是实现 TCP 通信的核心,需在项目配置中启用该模块。
二、项目创建与配置
1. 创建 Qt Widgets 项目
- 打开 Qt Creator,选择「New Project」→「Application」→「Qt Widgets Application」,设置项目名称(如
TcpClient)和保存路径。 - 选择基类为
QWidget(与示例代码一致),取消「Generate form」外的不必要选项,完成项目创建。
2. 配置项目文件(.pro)
TCP 通信依赖Qt Network模块,需在项目的.pro文件中添加该模块,否则会出现编译错误:
cpp
#-------------------------------------------------
#
# Project created by QtCreator 2017-02-12T17:03:25
#
#-------------------------------------------------
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = my_client
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp\
widget.cpp \
tcpsocket.cpp
HEADERS += widget.h \
tcpsocket.h
FORMS += widget.ui
三、界面设计(widget.ui)
示例代码中包含按钮、输入框、列表控件,需在 UI 设计器中完成以下布局:
- 控件添加 :
- 按钮 1(
pushButton):用于连接服务端,文本设置为「连接服务器」。 - 按钮 2(
pushButton_2):用于发送数据,文本设置为「发送」。 - 行编辑框(
lineEdit):用于输入要发送的文本内容。 - 列表控件(
listWidget):用于显示接收到的服务端数据。
- 按钮 1(
- 布局调整 :
- 可使用垂直布局 / 水平布局组合控件,确保界面美观且自适应窗口大小。
四、核心代码实现
1. 头文件声明(widget.h)
需声明自定义 TCP 套接字对象、槽函数(连接、发送、接收数据):
cpp
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class tcpsocket;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
void readData();
void on_pushButton_2_clicked();
private:
tcpsocket *socket;
Ui::Widget *ui;
};
#endif // WIDGET_H
2. 源文件实现(widget.cpp)
(1)构造函数初始化
设置窗口标题,初始化 UI:
cpp
#include "widget.h"
#include "ui_widget.h"
// 若使用自定义tcpsocket,包含对应头文件:#include "tcpsocket.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("客户端"); // 设置窗口标题
socket = nullptr; // 初始化套接字对象,避免野指针
}
Widget::~Widget()
{
delete ui;
// 析构时关闭套接字连接
if(socket != nullptr)
{
socket->disconnectFromHost();
socket->deleteLater();
}
}
(2)连接服务器功能
点击「连接服务器」按钮时,创建套接字对象并连接指定 IP 和端口:
cpp
void Widget::on_pushButton_clicked()
{
ui->pushButton->setEnabled(false);
QString ipAddress="192.168.10.2";
socket=new tcpsocket(this);
socket->connectToHost(ipAddress,8010);
connect(socket,SIGNAL(readyRead()),this,SLOT(readData()));
// 关联连接成功/失败信号,增加反馈
connect(socket, &QTcpSocket::connected, [=](){
ui->listWidget->addItem("成功连接到服务器!");
});
connect(socket, &QTcpSocket::disconnected, [=](){
ui->listWidget->addItem("与服务器断开连接!");
ui->pushButton->setEnabled(true); // 重新启用连接按钮
});
}
(3)接收服务端数据
当套接字有可读数据时,读取并显示到列表控件:
cpp
void Widget::readData()
{
// 读取所有接收到的数据
QByteArray buffer = socket->readAll();
if(!buffer.isEmpty())
{
qDebug() << "接收数据:" << buffer; // 控制台输出
ui->listWidget->addItem(buffer); // 界面显示
}
}
(4)发送数据到服务端
点击「发送」按钮时,将输入框的文本发送到服务端:
cpp
void Widget::on_pushButton_2_clicked()
{
// 获取输入框文本
QString str = ui->lineEdit->text();
if(str.isEmpty()) // 空内容不发送
return;
// 转换为UTF-8编码的字节数组(兼容中文)
QByteArray byte = str.toUtf8();
// 发送数据
socket->write(byte);
}
3. 自定义 tcpsocket 类
cpp
#ifndef TCPSOCKET_H
#define TCPSOCKET_H
#include <QObject>
#include <QTcpSocket>
class tcpsocket : public QTcpSocket
{
Q_OBJECT
public:
tcpsocket(QObject *parent);
};
#endif // TCPSOCKET_H
#include "tcpsocket.h"
tcpsocket::tcpsocket(QObject *parent):QTcpSocket(parent)
{
}

