文章目录
RK3568wifi_7">一、让RK3568开发板先连接上wifi
测试是否可以ping通百度:
二、客户端代码
1. widget.h
文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket> // 用于TCP连接
#include <QPushButton> // 按钮控件
#include <QTextEdit> // 文本显示控件
#include <QLineEdit> // 单行文本输入框
#include <QVBoxLayout> // 垂直布局管理器
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr); // 构造函数
~Widget(); // 析构函数
private slots:
void onConnectClicked(); // 连接到服务器的槽函数
void onSendMessageClicked(); // 发送消息到服务器的槽函数
void onDataReceived(); // 处理接收到的数据的槽函数
private:
QTcpSocket *socket; // 客户端连接对象
QTextEdit *logTextEdit; // 用于显示日志信息的文本框
QLineEdit *messageInput; // 输入消息的文本框
QPushButton *connectButton; // 连接服务器按钮
QPushButton *sendButton; // 发送消息按钮
void setupUI(); // 设置UI布局的函数
};
#endif // WIDGET_H
2. widget.cpp
文件
#include "widget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGuiApplication>
#include <QScreen>
Widget::Widget(QWidget *parent) :
QWidget(parent),
socket(new QTcpSocket(this)) // 初始化socket对象
{
setupUI(); // 设置UI界面
// 连接按钮的点击信号与槽函数
connect(connectButton, &QPushButton::clicked, this, &Widget::onConnectClicked);
// 连接发送按钮的点击信号与槽函数
connect(sendButton, &QPushButton::clicked, this, &Widget::onSendMessageClicked);
// 连接接收到数据的信号与槽函数
connect(socket, &QTcpSocket::readyRead, this, &Widget::onDataReceived);
}
Widget::~Widget()
{
delete socket; // 销毁socket对象
}
// 设置UI布局
void Widget::setupUI()
{
// 获取所有屏幕的信息,来设置窗口为当前屏幕的尺寸
QList <QScreen *> list_screen = QGuiApplication::screens();
// 设置窗口尺寸为第一个屏幕的宽度和高度
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
// 主垂直布局
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 创建日志显示框,设置为只读
logTextEdit = new QTextEdit(this);
logTextEdit->setReadOnly(true);
mainLayout->addWidget(logTextEdit); // 添加到布局中
// 输入框和发送按钮的水平布局
QHBoxLayout *inputLayout = new QHBoxLayout;
messageInput = new QLineEdit(this); // 创建输入框
inputLayout->addWidget(messageInput); // 将输入框添加到布局中
sendButton = new QPushButton("Send", this); // 创建发送按钮
inputLayout->addWidget(sendButton); // 将发送按钮添加到布局中
mainLayout->addLayout(inputLayout); // 将输入框和发送按钮的布局添加到主布局中
// 连接服务器按钮
connectButton = new QPushButton("Connect to Server", this);
mainLayout->addWidget(connectButton); // 添加到主布局中
// 设置整个布局
setLayout(mainLayout);
}
// 点击连接按钮时的槽函数
void Widget::onConnectClicked()
{
// 尝试连接到指定IP和端口的服务器
socket->connectToHost("192.168.0.165", 12345);
if (socket->waitForConnected()) {
logTextEdit->append("Connected to server!"); // 成功连接后显示日志
} else {
logTextEdit->append("Failed to connect to server!"); // 连接失败时显示日志
}
}
// 点击发送按钮时的槽函数
void Widget::onSendMessageClicked()
{
QString message = messageInput->text(); // 获取输入框中的消息
if (!message.isEmpty()) {
socket->write(message.toUtf8()); // 将消息转换为UTF-8字节流并发送
logTextEdit->append("Sent: " + message); // 显示已发送的消息
}
}
// 处理接收到的消息的槽函数
void Widget::onDataReceived()
{
QByteArray data = socket->readAll(); // 读取服务器发来的数据
logTextEdit->append("Received from server: " + data); // 显示收到的消息
}
详细讲解
1. Widget
类构造函数 (Widget::Widget
)
Widget::Widget(QWidget *parent) :
QWidget(parent),
socket(new QTcpSocket(this)) // 初始化socket对象
{
setupUI(); // 设置UI界面
}
- 在构造函数中,首先通过
socket(new QTcpSocket(this))
创建一个QTcpSocket
对象,该对象用于客户端和服务器之间的 TCP 通信。 - 调用
setupUI()
函数来设置界面。
2. UI 布局 (setupUI
)
void Widget::setupUI()
{
// 获取所有屏幕的信息,来设置窗口为当前屏幕的尺寸
QList <QScreen *> list_screen = QGuiApplication::screens();
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
...
}
- 使用
QGuiApplication::screens()
获取当前系统的所有屏幕信息,并设置窗口尺寸为第一个屏幕的分辨率(宽度和高度)。 - 使用
QVBoxLayout
创建一个垂直布局 (mainLayout
),将日志框和按钮按顺序添加到这个布局中。 - 通过
QHBoxLayout
组织输入框和发送按钮,输入框允许用户输入消息,点击 “Send” 按钮后,消息会被发送到服务器。
3. 连接按钮的槽函数 (onConnectClicked
)
void Widget::onConnectClicked()
{
socket->connectToHost("192.168.0.165", 12345); // 连接到本地 TCP 服务器
if (socket->waitForConnected()) {
logTextEdit->append("Connected to server!"); // 成功连接后显示日志
} else {
logTextEdit->append("Failed to connect to server!"); // 连接失败时显示日志
}
}
connectToHost("192.168.0.165", 12345)
尝试连接到指定 IP 地址和端口的服务器。- 如果连接成功,通过
waitForConnected()
确认连接,然后在日志框中显示"Connected to server!"
。 - 如果连接失败,则显示
"Failed to connect to server!"
。
4. 发送消息按钮的槽函数 (onSendMessageClicked
)
void Widget::onSendMessageClicked()
{
QString message = messageInput->text(); // 获取输入框中的消息
if (!message.isEmpty()) {
socket->write(message.toUtf8()); // 将消息转换为UTF-8字节流并发送
logTextEdit->append("Sent: " + message); // 显示已发送的消息
}
}
- 获取输入框中的消息,并通过
QTcpSocket::write()
将消息以 UTF-8 编码发送到服务器。 - 在日志框中显示
"Sent: "
和用户输入的消息。
5. 接收数据的槽函数 (onDataReceived
)
void Widget::onDataReceived()
{
QByteArray data = socket->readAll(); // 读取服务器发来的数据
logTextEdit->append("Received from server: " + data); // 显示收到的消息
}
- 通过
QTcpSocket::readyRead
信号,检测到服务器发送数据时,调用此槽函数。 - 使用
socket->readAll()
读取服务器发送的数据,并在日志框中显示"Received from server: "
和接收到的内容。
总结
- 本程序创建了一个简单的 TCP 客户端,能够连接到服务器并与其进行数据交互。
- 窗口界面包含:显示日志的文本框、输入消息的文本框、连接服务器的按钮和发送消息的按钮。
- 程序使用
QTcpSocket
类实现与服务器的连接和数据传输,能够实时显示连接状态、发送的消息和接收到的消息。
三、服务器代码
widget.h
(服务器端头文件)
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer> // 用于TCP服务器
#include <QTcpSocket> // 用于客户端连接
#include <QPushButton> // 按钮控件
#include <QTextEdit> // 文本显示控件
#include <QLineEdit> // 单行文本输入框
#include <QVBoxLayout> // 垂直布局管理器
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr); // 构造函数
~Widget(); // 析构函数
private slots:
void onStartServerClicked(); // 启动服务器按钮的槽函数
void onSendMessageClicked(); // 发送消息到客户端的槽函数
void onNewConnection(); // 处理新的客户端连接
void onDataReceived(); // 处理接收到的数据
private:
QTcpServer *server; // 服务器对象
QTcpSocket *clientSocket; // 客户端连接对象
QTextEdit *logTextEdit; // 用于显示日志信息的文本框
QLineEdit *messageInput; // 输入消息的文本框
QPushButton *startServerButton; // 启动服务器按钮
QPushButton *sendButton; // 发送消息按钮
void setupUI(); // 设置UI布局的函数
};
#endif // WIDGET_H
widget.cpp
(服务器端实现)
#include "widget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGuiApplication>
#include <QScreen>
Widget::Widget(QWidget *parent) :
QWidget(parent),
server(new QTcpServer(this)) // 创建一个 TCP 服务器对象
{
setupUI(); // 设置UI界面
// 连接启动服务器按钮的点击信号与槽函数
connect(startServerButton, &QPushButton::clicked, this, &Widget::onStartServerClicked);
// 连接发送按钮的点击信号与槽函数
connect(sendButton, &QPushButton::clicked, this, &Widget::onSendMessageClicked);
// 连接新客户端连接的信号与槽函数
connect(server, &QTcpServer::newConnection, this, &Widget::onNewConnection);
}
Widget::~Widget()
{
delete server; // 销毁 TCP 服务器对象
}
// 设置UI布局
void Widget::setupUI()
{
// 获取所有屏幕的信息,来设置窗口为当前屏幕的尺寸
QList <QScreen *> list_screen = QGuiApplication::screens();
// 设置窗口尺寸为第一个屏幕的宽度和高度
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
// 主垂直布局
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 创建日志显示框,设置为只读
logTextEdit = new QTextEdit(this);
logTextEdit->setReadOnly(true);
mainLayout->addWidget(logTextEdit); // 添加到布局中
// 输入框和发送按钮的水平布局
QHBoxLayout *inputLayout = new QHBoxLayout;
messageInput = new QLineEdit(this); // 创建输入框
inputLayout->addWidget(messageInput); // 将输入框添加到布局中
sendButton = new QPushButton("Send", this); // 创建发送按钮
inputLayout->addWidget(sendButton); // 将发送按钮添加到布局中
mainLayout->addLayout(inputLayout); // 将输入框和发送按钮的布局添加到主布局中
// 启动服务器按钮
startServerButton = new QPushButton("Start Server", this);
mainLayout->addWidget(startServerButton); // 添加到主布局中
// 设置整个布局
setLayout(mainLayout);
}
// 点击启动服务器按钮时的槽函数
void Widget::onStartServerClicked()
{
if (server->listen(QHostAddress::Any, 12345)) { // 在任意网络接口的12345端口上监听
logTextEdit->append("Server started, waiting for connections...");
} else {
logTextEdit->append("Failed to start server.");
}
}
// 点击发送按钮时的槽函数
void Widget::onSendMessageClicked()
{
QString message = messageInput->text(); // 获取输入框中的消息
if (clientSocket && !message.isEmpty()) {
clientSocket->write(message.toUtf8()); // 将消息转换为UTF-8字节流并发送到客户端
logTextEdit->append("Sent: " + message); // 显示已发送的消息
}
}
// 处理新连接的槽函数
void Widget::onNewConnection()
{
clientSocket = server->nextPendingConnection(); // 获取新的客户端连接
logTextEdit->append("New client connected.");
// 连接客户端的数据接收信号与槽函数
connect(clientSocket, &QTcpSocket::readyRead, this, &Widget::onDataReceived);
// 连接客户端断开连接的信号与槽函数
connect(clientSocket, &QTcpSocket::disconnected, clientSocket, &QTcpSocket::deleteLater);
}
// 处理接收到的数据的槽函数
void Widget::onDataReceived()
{
if (clientSocket) {
QByteArray data = clientSocket->readAll(); // 读取客户端发来的数据
logTextEdit->append("Received from client: " + data); // 显示接收到的消息
}
}
详细讲解
1. Widget
类构造函数 (Widget::Widget
)
Widget::Widget(QWidget *parent) :
QWidget(parent),
server(new QTcpServer(this)) // 创建一个 TCP 服务器对象
{
setupUI(); // 设置UI界面
}
- 创建
QTcpServer
对象server
,该对象将用于在指定端口上监听客户端的连接。
2. UI 布局 (setupUI
)
void Widget::setupUI()
{
QList <QScreen *> list_screen = QGuiApplication::screens();
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
...
}
- 和客户端一样,获取当前屏幕的尺寸并将窗口设置为最大化。
- 使用
QVBoxLayout
创建垂直布局mainLayout
,并添加用于显示日志的QTextEdit
控件。 - 创建一个水平布局
inputLayout
,包含一个输入框和一个发送按钮。 - 创建并添加一个 “Start Server” 按钮,用于启动服务器。
3. 启动服务器 (onStartServerClicked
)
void Widget::onStartServerClicked()
{
if (server->listen(QHostAddress::Any, 12345)) { // 在任意网络接口的12345端口上监听
logTextEdit->append("Server started, waiting for connections...");
} else {
logTextEdit->append("Failed to start server.");
}
}
listen()
函数用于启动服务器并在12345
端口上监听客户端的连接。如果成功,输出 “Server started” 日志,否则输出错误日志。
4. 处理新的客户端连接 (onNewConnection
)
void Widget::onNewConnection()
{
clientSocket = server->nextPendingConnection(); // 获取新的客户端连接
logTextEdit->append("New client connected.");
...
}
- 使用
nextPendingConnection()
获取新的客户端连接,并通过clientSocket
进行数据交互。 - 在此槽函数中连接客户端的
readyRead
信号(接收到数据时)和disconnected
信号(客户端断开连接时)。
5. 发送消息到客户端 (onSendMessageClicked
)
void Widget::onSendMessageClicked()
{
QString message = messageInput->text(); // 获取输入框中的消息
if (clientSocket && !message.isEmpty()) {
clientSocket->write(message.toUtf8()); // 将消息转换为UTF-8字节流并发送到客户端
logTextEdit->append("Sent: " + message); // 显示已发送的消息
}
}
- 如果客户端已经连接,并且用户输入了消息,使用
clientSocket->write()
发送数据到客户端。 - 在日志框中显示发送的消息。
6. 接收客户端数据 (onDataReceived
)
void Widget::onDataReceived()
{
if (clientSocket) {
QByteArray data = clientSocket->readAll(); // 读取客户端发来的数据
logTextEdit->append("Received from client: " + data); // 显示接收到的消息
}
}
- 当客户端发送数据时,使用
readAll()
读取数据并显示在日志框中。