QT学习笔记之TCP通信1(TCP服务器)

一、创建TCP服务器

1.   TCP编程用到两类:QTcpServerQTcpSocket

      QTcpServer:QTcpServer类用于创建TCP服务器。它监听来自客户端的连接请求,并为每个接受的连接创建一个QTcpSocket对象。服务器可以处理多个并发连接,因为它是非阻塞的,并且可以同时监听多个客户端。

示例代码:    
    QTcpServer *tcpServer = new QTcpServer(this);

    connect(tcpServer, &QTcpServer::newConnection, this, [tcpServer](){

        QTcpSocket *socket = tcpServer->nextPendingConnection();

        connect(socket, &QTcpSocket::readyRead, this, [socket](){});// 读取数据

        connect(socket, &QTcpSocket::disconnected, this, [socket](){});// 客户端断开连接

    });

    tcpServer->listen(QHostAddress::Any, 1234); // 监听所有地址的1234端口

在这个例子中,tcpServer对象被创建并监听所有IP地址的1234端口。每当有新的客户端连接时,newConnection信号被触发,创建一个新的QTcpSocket来处理该连接。

      QtcpSocketQTcpSocket类用于创建TCP客户端或处理服务器端的连接。作为客户端,它提供连接到服务器、发送数据和接收数据的功能。作为服务器端,它用于处理由QTcpServer接受的新连接。

示例代码(作为客户端使用):    
    QTcpSocket *tcpSocket = new QTcpSocket(this);

    connect(tcpSocket, &QTcpSocket::readyRead, this, [tcpSocket](){});// 读取数据

    connect(tcpSocket, &QTcpSocket::disconnected, this, [tcpSocket](){});// 客户端断开连接

    tcpSocket->connectToHost("serverAddress", 1234); // 连接到服务器

在这个例子中,tcpSocket对象被创建并尝试连接到指定的服务器地址和端口。

2.   创建TCP服务器QTcpServer和QTcpSocket两个类都要用到;

      创建TCP客户端只需要用到QTcpSocket类。

二、新建QT工程

第一步:打开QT软件,新建工程;

第二步:选择一个模板(默认即可);

第三步:设置项目名称以及项目存储路径;

第四步:编译器选择(默认即可)

第五步:基类选择(QWidget

第六步:项目管理(默认即可)

三、新类的使用(QTcpServer Class和QTcpSocket Class)

步骤:帮助->索引->搜索“QTcpServer类”

      1. 在widget.h文件中,添加所用头文件;

      2. 在.pro文件中,添加network;

      3. 定义指针变量,用于创建和操作TCP服务器和客户端(widget.h);

      4.在构造函数中,使用new关键字,为指针变量分配内存,初始化指针。(widget.cpp)

 

四、设置UI界面

1. 接收框:Plain Text Edit控件(重命名:receiveEdit)

2. 发送框:Line Edit控件(重命名:sendEdit)

3. 接收窗口和发送窗口:Group Box控件

4. 端口号框:Line Edit(重命名:portEdit) + Label控件

5. 按钮:PushButton 控件

打开服务器(重命名:openBt)、关闭服务器(重命名:closeBt)、发送(重命名:sendBt)

五、功能实现逻辑代码编写

服务器所需要实现的功能:

①打开服务器:打开服务器,并监听指定端口的客户端数据;

②建立与TCP客户端的连接,并接收显示数据;

③服务器发送数据至客户端;

④关闭服务器。

1. 打开服务器,并监听指定端口的客户端数据

      第一步:关联“打开服务器按钮控件”信号和槽(自动关联)

  

      第二步:编写代码,监听(ui->portEdit->text().toUInt())的客户端数据;

Public Functions

bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)

注释:Widget::on_openBt_clicked() 是一个槽函数,它在名为 openBt 的按钮被点击时触发。这个函数的作用是启动一个TCP服务器并监听指定的端口。

1. tcpServer->listen(QHostAddress::Any, ui->portEdit->text().toUInt());

这行代码是函数的核心,它调用了 listen 方法来启动服务器的监听功能。QHostAddress::Any 表示服务器将监听所有可用的网络接口,这样无论是来自局域网还是广域网的连接请求都能被接受。

- `QHostAddress::Any`: 这是一个特殊的地址,它指示服务器绑定到所有的网络接口上。这意味着服务器可以接受来自任何IP地址的连接。

ui->portEdit->text().toUInt() 这部分代码的作用是从用户界面的某个编辑框(portEdit)中获取文本(端口号),并将其转换为无符号整数(toUInt()),代表服务器将要监听的端口号。用户可以在用户界面中输入希望服务器监听的端口号。

2. tcpServer 是一个指向 QTcpServer 类的实例的指针。QTcpServer Qt框架中用于创建TCP服务器的类。在这段代码被执行之前,tcpServer 指针应该已经被正确地初始化并指向了一个有效的 QTcpServer 对象。

3. listen 方法是 QTcpServer 类的一个成员函数,它的作用是让服务器开始监听指定的端口。如果监听成功,该方法会返回 true;如果端口已经被占用或其他原因导致监听失败,它会返回 false

综上所述,这行代码的作用是启动一个TCP服务器,使其在所有网络接口上监听由用户界面指定的端口号。例如,如果用户在portEdit中输入了1234,那么服务器将开始监听端口1234上的连接请求。

2. 建立与TCP客户端的连接,并接收显示数据

      第一步:建立与TCP客户端的连接(手动关联)

① 在widget.cpp文件中的构造函数中编写代码,建立一个信号与槽的连接,用于新的客户端接到服务器:

 

注释:这行代码是Qt框架中使用信号和槽机制的一个典型例子。在这里,connect函数被用来将tcpServer对象的newConnection信号连接到this对象的newConnection_Slot槽函数上。

1. tcpServer 是一个 QTcpServer 类型的指针,它代表了一个TCP服务器。

2. SIGNAL(newConnection()) QTcpServer 类的一个信号,当有新的客户端连接到服务器时,这个信号会被触发。

3. this 指的是当前对象的指针,通常是 Widget 类的实例。

4. SLOT(newConnection_Slot()) Widget 类中的一个槽函数,当newConnection信号被触发时,这个槽函数将被调用。

通过这种方式,当tcpServer接受到一个新的客户端连接时,newConnection_Slot函数将自动执行,允许你在该函数中编写代码来处理新的连接,例如创建一个新的QTcpSocket来管理与客户端的通信,或者将新的连接信息传递给其他处理函数。

② 在widget.h文件中定义槽函数:void newConnection_Slot()

 

注释:在QWidget派生类的Widget类中的私有槽函数private slots中定义新的槽函数,用于处理新的连接,当tcpServer接受到新的客户端连接时,这个槽函数会被触发。

③在widget.cpp文件中,编写槽函数void Widget::newConnection_Slot()代码

注释:该槽函数在QTcpServer对象的newConnection信号被触发时执行。这个信号通常在有新的客户端尝试连接到服务器时发出。槽函数的作用是处理这个新的连接,并准备接收数据。

获取新的QTcpSocket对象:tcpSocket = tcpServer->nextPendingConnection();

这行代码从tcpServer对象中获取一个新的QTcpSocket对象,该对象代表了一个新的客户端连接。nextPendingConnection方法返回一个未处理的连接,这样您就可以对其进行操作,比如读取数据或发送响应。

      第二步:接收数据,并将数据显示在接收框内

① 在widget.cpp文件中的槽函数void newConnection_Slot()中编写代码:

注释:连接readyRead信号到readyRead_Slot槽函数:

connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot()));

这行代码建立了tcpSocketreadyRead信号与Widget类的readyRead_Slot槽函数之间的连接。当tcpSocket对象有数据可读时,readyRead信号会被触发,这时readyRead_Slot函数将被调用以处理接收到的数据。

② 在widget.h文件中定义槽函数:void readyRead_Slot()

注释:在QWidget派生类的Widget类中的私有槽函数private slots中定义新的槽函数,用于读取从客户端接收的数据,当tcpSocket有数据可读时,这个槽函数会被调用。

③在widget.cpp文件中,编写槽函数void Widget::readyRead_Slot()代码

注释:这段代码定义了Widget类中的一个槽函数readyRead_Slot,它在QTcpSocket对象的readyRead信号被触发时执行。这个信号通常在有数据可读时发出,即当一个与QTcpSocket关联的TCP连接上有数据传入时。

下面是readyRead_Slot函数的工作流程:

1. 声明一个QString类型的变量buf,用于存储读取的数据。

2.调用tcpSocket->readAll(),这是一个QTcpSocket类的方法,它读取所有可用的数据,并将其存储在buf变量中。readAll方法会尝试读取当前所有可用的数据,直到遇到一个不包含数据的读取尝试。

3.调用ui->receiveEdit->appendPlainText(buf),这是一个将文本添加到用户界面元素(假设是QTextEditQPlainTextEdit)的方法。ui是一个指向用户界面的指针,它通常是由QtUI设计器生成的UI类。receiveEdit是用户界面中的一个文本编辑器控件,用于显示接收到的数据。appendPlainText方法将buf中的文本添加到receiveEdit控件的末尾,而不添加任何格式化。

这个槽函数的作用是将从TCP连接接收到的数据实时显示在用户界面上,为用户提供一个可视化的方式来查看通信数据。这是网络应用程序中常见的一种做法,它允许用户监控和调试网络通信。

3. 服务器发送数据至客户端

第一步:关联“发送按钮控件”信号和槽(自动关联)

 

第二步:编写代码,将(ui->sendEdit)控件输入的数据发送给的客户端;

注释:这段代码定义了`Widget`类中的一个槽函数`on_sendBt_clicked`,该函数在用户点击某个触发发送数据动作的按钮(假设按钮对象名为`sendBt`)时被调用。这个槽函数的作用是通过已建立的TCP连接发送数据。

以下是`on_sendBt_clicked`函数的工作流程:

1. 获取用户输入的文本:

   `ui->sendEdit->text()`这行代码通过`sendEdit`控件(假设是一个`QLineEdit`或其他文本输入控件)获取用户输入的文本。用户通过这个控件输入他们想要发送的数据。

2. 将文本转换为本地8位字符序列:

   `.toLocal8Bit()``toLocal8Bit`是一个QString类的方法,它将QString对象中的文本转换为本地编码的8位字符序列。这是因为`QTcpSocket``write`方法需要一个`const char*`类型的参数,而QString对象包含的是Unicode字符。

3. 调用`data()`方法:

   `.data()``data`方法返回一个指向转换后的8位字符序列的指针。这个指针被用作`write`方法的参数。

4. 发送数据:

   `tcpSocket->write()``write`方法是`QTcpSocket`类的一个成员函数,它将提供的数据通过当前的TCP连接发送到远程主机。在这个例子中,它发送用户通过`sendEdit`输入框输入的文本。

这个槽函数使得用户界面能够与网络通信功能交互,允许用户通过点击按钮来发送数据。这是创建交互式网络应用程序的一个重要组成部分。需要注意的是,`tcpSocket`变量应该在调用`on_sendBt_clicked`之前已经被初始化并与某个远程主机建立了连接。此外,为了确保槽函数能够正常工作,`tcpSocket``sendEdit`必须有效,且`ui`指针应该正确指向了包含这些控件的用户界面。

4. 关闭服务器

实现逻辑:点击关闭服务器按钮时,关闭之前通过 tcpServer 对象启动的TCP服务器。

第一步:关联“关闭服务器按钮控件”信号和槽(自动关联);

第二步:编写代码,关闭之前通过 tcpServer 对象启动的TCP服务器;

注释:Widget::on_closeBt_clicked() 是一个槽函数,它在某个名为 closeBt 的按钮被点击时触发。这个函数的作用是关闭之前通过 tcpServer 对象启动的TCP服务器。

tcpServer->close();这行代码调用了 close 方法来关闭 QTcpServer 对象。QTcpServer Qt框架中用于创建TCP服务器的类。当这个方法被调用时,如果服务器正在监听某个端口,它将停止监听,并且关闭所有已建立的连接。

为了使这段代码能够正常工作,您需要确保以下几点:

1. tcpServer 指针已经被正确初始化,并且指向了一个有效的 QTcpServer 对象。

2. 在调用 close 方法之前,tcpServer 对象应该已经通过 listen 方法启动并开始监听端口。

3. 应用程序已经包含了Qt网络模块,并且正确链接了相关的库文件。

这段代码通常位于某个Qt应用程序中,它是一个槽函数,用于响应用户界面中的按钮点击事件。当用户点击关闭按钮时,这个槽函数会被触发,执行关闭服务器的操作。这是一种常见的模式,用于在图形用户界面程序中实现用户交互功能。

【笔记学习自北京讯为电子嵌入式学习之QT学习篇】

  • 34
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
QT TCP客户端与服务器通信的步骤如下: 1. 创建QT TCP客户端对象 使用QT提供的QTcpSocket类创建TCP客户端对象。可以使用new运算符在堆上动态分配内存,也可以在栈上创建对象。 ``` QTcpSocket *client = new QTcpSocket(this); // 动态分配内存 ``` 2. 连接服务器 使用client对象的connectToHost()函数连接服务器。该函数需要传递服务器IP地址和端口号。 ``` client->connectToHost("127.0.0.1", 8888); // 连接服务器 ``` 3. 发送数据 使用client对象的write()函数发送数据。该函数需要传递待发送的数据和数据长度。 ``` QByteArray data = "Hello World!"; client->write(data, data.length()); // 发送数据 ``` 4. 接收数据 使用client对象的readyRead()信号接收服务器发送的数据。可以使用client对象的read()函数读取接收到的数据。 ``` connect(client, SIGNAL(readyRead()), this, SLOT(readData())); ``` ``` void readData() { QByteArray data = client->readAll(); // 读取数据 qDebug() << data; } ``` 5. 断开连接 使用client对象的disconnectFromHost()函数断开与服务器的连接。 ``` client->disconnectFromHost(); // 断开连接 ``` 完整的QT TCP客户端代码如下: ``` #include <QTcpSocket> class Client : public QObject { Q_OBJECT public: Client(QObject *parent = nullptr); ~Client(); private slots: void readData(); private: QTcpSocket *client; }; Client::Client(QObject *parent) : QObject(parent) { client = new QTcpSocket(this); client->connectToHost("127.0.0.1", 8888); connect(client, SIGNAL(readyRead()), this, SLOT(readData())); } Client::~Client() { client->disconnectFromHost(); } void Client::readData() { QByteArray data = client->readAll(); qDebug() << data; } ``` 注意:QTcpSocket是异步的,因此需要使用信号和槽机制来处理数据接收。同时,需要在客户端对象的析构函数中调用disconnectFromHost()函数断开与服务器的连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值