八卦阵 发表于 2024-9-16 23:57:41

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

一、创建TCP服务器

1.   TCP编程用到两类:QTcpServer和QTcpSocket。
      QTcpServer:QTcpServer类用于创建TCP服务器。它监听来自客户端的毗连请求,并为每个接受的毗连创建一个QTcpSocket对象。服务器可以处理多个并发毗连,由于它黑白阻塞的,而且可以同时监听多个客户端。
   示例代码:   
    QTcpServer *tcpServer = new QTcpServer(this);

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

        QTcpSocket *socket = tcpServer->nextPendingConnection();

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

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

    });

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

在这个例子中,tcpServer对象被创建并监听所有IP地址的1234端口。每当有新的客户端连接时,newConnection信号被触发,创建一个新的QTcpSocket来处理该连接。          QtcpSocket:QTcpSocket类用于创建TCP客户端或处理服务器端的毗连。作为客户端,它提供毗连到服务器、发送数据和接收数据的功能。作为服务器端,它用于处理由QTcpServer接受的新毗连。
   示例代码(作为客户端使用):   
    QTcpSocket *tcpSocket = new QTcpSocket(this);

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

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

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

在这个例子中,tcpSocket对象被创建并尝试连接到指定的服务器地址和端口。    2.   创建TCP服务器QTcpServer和QTcpSocket两个类都要用到;
      创建TCP客户端只须要用到QTcpSocket类。

   二、新建QT工程

第一步:打开QT软件,新建工程;
https://i-blog.csdnimg.cn/blog_migrate/788549d6b4ce993d00441af16f97dcf5.png
第二步:选择一个模板(默认即可);
https://i-blog.csdnimg.cn/blog_migrate/4b2f1af38c5e98f0362cb3092213888c.png
第三步:设置项目名称以及项目存储路径;
https://i-blog.csdnimg.cn/blog_migrate/bcf049d7be0ab3a12184177cd458ff5d.png
第四步:编译器选择(默认即可)
https://i-blog.csdnimg.cn/blog_migrate/4e283a30a5e05ec90ad73b2b4b50735c.png
第五步:基类选择(QWidget)
https://i-blog.csdnimg.cn/blog_migrate/be957172dbead14acdd7ba2e367e8a45.png
第六步:项目管理(默认即可)
https://i-blog.csdnimg.cn/blog_migrate/2357dff40b0fe56f6c52fe7027e12a39.png

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

步调:帮助->索引->搜索“QTcpServer类”
https://i-blog.csdnimg.cn/blog_migrate/bde16dd88bee92996051a482947ad367.png
      1. 在widget.h文件中,添加所用头文件;

https://i-blog.csdnimg.cn/blog_migrate/0198a0150a16686aaf4c6517db248987.png
      2. 在.pro文件中,添加network;

https://i-blog.csdnimg.cn/blog_migrate/2812202814fb1d8c5d3715cd45c875b1.png
      3. 定义指针变量,用于创建和操作TCP服务器和客户端(widget.h);

https://i-blog.csdnimg.cn/blog_migrate/b05af3d03cb1615719e959b2b4fccd12.png
      4.在构造函数中,使用new关键字,为指针变量分配内存,初始化指针。(widget.cpp)

https://i-blog.csdnimg.cn/blog_migrate/8e50ccc533ed97f0607cca10f5a5992c.png
 
四、设置UI界面

1. 接收框:Plain Text Edit控件(重定名:receiveEdit)
2. 发送框:Line Edit控件(重定名:sendEdit)
3. 接收窗口和发送窗口:Group Box控件
4. 端标语框:Line Edit(重定名:portEdit) + Label控件
5. 按钮:PushButton 控件
打开服务器(重定名:openBt)、关闭服务器(重定名:closeBt)、发送(重定名:sendBt)
https://i-blog.csdnimg.cn/blog_migrate/8a5211b073cbfb3691bd2a4abfa943be.png


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

服务器所须要实现的功能:
①打开服务器:打开服务器,并监听指定端口的客户端数据;
②创建与TCP客户端的毗连,并接收显示数据;
③服务器发送数据至客户端;
④关闭服务器。
1. 打开服务器,并监听指定端口的客户端数据

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

https://i-blog.csdnimg.cn/blog_migrate/9704271e828a6c6c27d301c5ff0fb4ba.png   https://i-blog.csdnimg.cn/blog_migrate/08219038eedaf9b996a2845d0a5713a3.png
      第二步:编写代码,监听(ui->portEdit->text().toUInt())的客户端数据;

   Public Functions
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
https://i-blog.csdnimg.cn/blog_migrate/a2a1c8e9e5f70023b828a225fad9c6aa.png
   注释: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文件中的构造函数中编写代码,创建一个信号与槽的毗连,用于新的客户端接到服务器:

https://i-blog.csdnimg.cn/blog_migrate/8ff25737f776dd5887f8c556d9a7aca6.png  
   注释:这行代码是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()

https://i-blog.csdnimg.cn/blog_migrate/f4711ea30a4d429cd6e6fc3c4d498a6a.png  
   注释:在QWidget派生类的Widget类中的私有槽函数private slots中定义新的槽函数,用于处理新的毗连,当tcpServer接受到新的客户端毗连时,这个槽函数会被触发。
③在widget.cpp文件中,编写槽函数void Widget::newConnection_Slot()代码

https://i-blog.csdnimg.cn/blog_migrate/bdb0294d97ba6824af8dde6ace25ef29.png
   注释:该槽函数在QTcpServer对象的newConnection信号被触发时实行。这个信号通常在有新的客户端尝试毗连到服务器时发出。槽函数的作用是处理这个新的毗连,并预备接收数据。
获取新的QTcpSocket对象:tcpSocket = tcpServer->nextPendingConnection();
这行代码从tcpServer对象中获取一个新的QTcpSocket对象,该对象代表了一个新的客户端毗连。nextPendingConnection方法返回一个未处理的毗连,这样您就可以对其进行操作,比如读取数据或发送响应。
      第二步:接收数据,并将数据显示在接收框内

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

https://i-blog.csdnimg.cn/blog_migrate/b8c13ca3b28443976255f3e9add2c612.png
   注释:毗连readyRead信号到readyRead_Slot槽函数:
connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(readyRead_Slot()));
这行代码创建了tcpSocket的readyRead信号与Widget类的readyRead_Slot槽函数之间的毗连。当tcpSocket对象有数据可读时,readyRead信号会被触发,这时readyRead_Slot函数将被调用以处理接收到的数据。
② 在widget.h文件中定义槽函数:void readyRead_Slot()

https://i-blog.csdnimg.cn/blog_migrate/59a5b503c2461bba03a7ed9369389058.png
   注释:在QWidget派生类的Widget类中的私有槽函数private slots中定义新的槽函数,用于读取从客户端接收的数据,当tcpSocket有数据可读时,这个槽函数会被调用。
③在widget.cpp文件中,编写槽函数void Widget::readyRead_Slot()代码

https://i-blog.csdnimg.cn/blog_migrate/dad7aee6e88bd6729d802ad5b8108489.png
   注释:这段代码定义了Widget类中的一个槽函数readyRead_Slot,它在QTcpSocket对象的readyRead信号被触发时实行。这个信号通常在有数据可读时发出,即当一个与QTcpSocket关联的TCP毗连上有数据传入时。
下面是readyRead_Slot函数的工作流程:
1. 声明一个QString范例的变量buf,用于存储读取的数据。
2.调用tcpSocket->readAll(),这是一个QTcpSocket类的方法,它读取所有可用的数据,并将其存储在buf变量中。readAll方法会尝试读取当前所有可用的数据,直到遇到一个不包罗数据的读取尝试。
3.调用ui->receiveEdit->appendPlainText(buf),这是一个将文本添加到用户界面元素(假设是QTextEdit或QPlainTextEdit)的方法。ui是一个指向用户界面的指针,它通常是由Qt的UI筹划器生成的UI类。receiveEdit是用户界面中的一个文本编辑器控件,用于显示接收到的数据。appendPlainText方法将buf中的文本添加到receiveEdit控件的末了,而不添加任何格式化。
这个槽函数的作用是将从TCP毗连接收到的数据实时显示在用户界面上,为用户提供一个可视化的方式来查看通信数据。这是网络应用程序中常见的一种做法,它允许用户监控和调试网络通信。
3. 服务器发送数据至客户端

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

https://i-blog.csdnimg.cn/blog_migrate/c0bb51275d185de9ab4a7fc2c9bddf32.png  https://i-blog.csdnimg.cn/blog_migrate/36da9ade5cd7a724ae8a1fe0d82f3870.png
第二步:编写代码,将(ui->sendEdit)控件输入的数据发送给的客户端;

https://i-blog.csdnimg.cn/blog_migrate/dd1c5f88a3edf2158166764ca53a9d55.png
   注释:这段代码定义了`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服务器。
第一步:关联“关闭服务器按钮控件”信号和槽(主动关联);

https://i-blog.csdnimg.cn/blog_migrate/811e3fe334dcc1d8cb1e798a885c8543.pnghttps://i-blog.csdnimg.cn/blog_migrate/b1b35560630504c6d879da944f37bbaf.png
第二步:编写代码,关闭之前通过 tcpServer 对象启动的TCP服务器;

https://i-blog.csdnimg.cn/blog_migrate/70d2e0562636dea2720b3ffb796723cf.png
   注释: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学习篇】

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: QT学习条记之TCP通信1(TCP服务器)