一、创建TCP服务器
1. TCP编程用到两类:QTcpServer和QTcpSocket。
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来处理该连接。
QtcpSocket:QTcpSocket类用于创建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(constQHostAddress&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()));
这行代码建立了tcpSocket的readyRead信号与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),这是一个将文本添加到用户界面元素(假设是QTextEdit或QPlainTextEdit)的方法。ui是一个指向用户界面的指针,它通常是由Qt的UI设计器生成的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学习篇】