Qt网络通信服务端与客户端学习
一、项目概述
本项目基于Qt框架实现了TCP服务端与客户端的基本通信,涵盖连接、消息收发、断开管理等功能,适合初学者系统学习Qt网络模块的实际用法。
二、项目结构
- 52/ 服务端:main.cpp、widget.cpp、widget.h
- 53/ 客户端:main.cpp、widget.cpp、widget.h
三、环境配置
- Qt 5.x及以上
- 启用network、widgets模块
- C++11支持
四、服务端核心代码详解(52目录)
1. main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
2. widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = nullptr);~Widget();
private:Ui::Widget *ui; // UI指针QTcpServer *tcpServer; // TCP服务端对象
private slots:void mNewConnetion(); // 新连接处理槽void receiveMessages(); // 接收消息槽void mStateChanged(QAbstractSocket::SocketState); // 连接状态变化槽void on_pushButton_3_clicked(); // 发送消息按钮槽void on_pushButton_clicked(); // 开始监听按钮槽void on_pushButton_2_clicked(); // 停止监听按钮槽
};
#endif // WIDGET_H
3. widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);tcpServer = new QTcpServer(this);this->setWindowTitle("服务端");connect(tcpServer, SIGNAL(newConnection()), this, SLOT(mNewConnetion()));ui->pushButton_2->setEnabled(false);
}
Widget::~Widget()
{delete ui;
}
void Widget::mNewConnetion()
{QTcpSocket *tmpTcpSocket = tcpServer->nextPendingConnection();QString ipaddr = tmpTcpSocket->peerAddress().toString();quint16 port = tmpTcpSocket->peerPort();ui->textBrowser->append("服务端:客户端的ip地址:" + ipaddr);ui->textBrowser->append("服务端:客户端的端口:" + QString::number(port));connect(tmpTcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessages()));connect(tmpTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
}
void Widget::receiveMessages()
{QTcpSocket *tmpTcpSocket = (QTcpSocket *)sender();ui->textBrowser->append("客户端:" + tmpTcpSocket->readAll());
}
void Widget::mStateChanged(QAbstractSocket::SocketState state)
{QTcpSocket *tmpTcpSocket = (QTcpSocket *)sender();switch (state) {case QAbstractSocket::UnconnectedState:ui->textBrowser->append("服务端:客户端断开连接");tmpTcpSocket->deleteLater();break;case QAbstractSocket::ConnectedState:ui->textBrowser->append("服务端:客户端已连接");break;default:break;}
}
void Widget::on_pushButton_3_clicked()
{QList <QTcpSocket *> socketList = tcpServer->findChildren<QTcpSocket *>();qDebug() << "tcpSocket 数量:" << socketList.count() << endl;if (socketList.count() == 0) {ui->textBrowser->append("当前没有客户端连接,请先与客户端连接!");return;}foreach (QTcpSocket *tmpTcpSocket, socketList) {tmpTcpSocket->write(ui->lineEdit->text().toUtf8());}ui->textBrowser->append("服务端:" + ui->lineEdit->text());
}
void Widget::on_pushButton_clicked()
{tcpServer->listen(QHostAddress("192.168.1.59"), 9999);ui->textBrowser->append("服务端:监听的ip地址和端口:192.168.1.59,9999");ui->pushButton_2->setEnabled(true);ui->pushButton->setEnabled(false);
}
void Widget::on_pushButton_2_clicked()
{tcpServer->close();ui->pushButton->setEnabled(true);ui->pushButton_2->setEnabled(false);
}
五、客户端核心代码详解(53目录)
1. main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
2. widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = nullptr);~Widget();
private:Ui::Widget *ui; // UI指针QTcpSocket *tcpSocket; // TCP客户端对象
private slots:void receiveMessages(); // 接收消息槽void mStateChanged(QAbstractSocket::SocketState); // 连接状态变化槽void on_pushButton_3_clicked(); // 发送消息按钮槽void on_pushButton_clicked(); // 连接服务端按钮槽void on_pushButton_2_clicked(); // 断开连接按钮槽
};
#endif // WIDGET_H
3. widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("客户端");ui->pushButton_2->setEnabled(false);tcpSocket = new QTcpSocket(this);connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessages()));connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
}
Widget::~Widget()
{delete ui;
}
void Widget::receiveMessages()
{ui->textBrowser->append("服务端:" + tcpSocket->readAll());
}
void Widget::mStateChanged(QAbstractSocket::SocketState state)
{switch (state) {case QAbstractSocket::UnconnectedState:ui->textBrowser->append("客户端:与服务端断开连接");ui->pushButton->setEnabled(true);ui->pushButton_2->setEnabled(false);break;case QAbstractSocket::ConnectedState:ui->textBrowser->append("客户端:已连接服务端");ui->pushButton->setEnabled(false);ui->pushButton_2->setEnabled(true);break;default:break;}
}
void Widget::on_pushButton_3_clicked()
{if (tcpSocket->state() == QAbstractSocket::ConnectedState) {tcpSocket->write(ui->lineEdit->text().toUtf8());ui->textBrowser->append("客户端:" + ui->lineEdit->text());} elseui->textBrowser->append("请先与服务端连接!");
}
void Widget::on_pushButton_clicked()
{ui->textBrowser->append("客户端:监听的ip地址和端口:192.168.1.59,9999");tcpSocket->connectToHost(QHostAddress("192.168.1.59"), 9999);
}
void Widget::on_pushButton_2_clicked()
{tcpSocket->disconnectFromHost();
}