1> 思維導(dǎo)圖
2> 手動完成服務(wù)器的實現(xiàn),并具體程序要注釋清楚
?widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer> //服務(wù)器類
#include <QTcpSocket> //客戶端類
#include <QMessageBox> //對話框類
#include <QList> //鏈表容器,用于存放客戶端套接字
#include <QDebug> //信息調(diào)試類
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_startBtn_clicked();
void newConnection_slot();
void readyRead_slot();
private:
Ui::Widget *ui;
//定義服務(wù)器指針
QTcpServer *server;
//定義客戶端容器
QList<QTcpSocket*> socketList;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//給服務(wù)器指針實例化空間
server = new QTcpServer(this); //創(chuàng)建一個服務(wù)器
}
Widget::~Widget()
{
delete ui;
}
//"啟動服務(wù)器" 對應(yīng)的槽函數(shù)
void Widget::on_startBtn_clicked()
{
//獲取ui界面上的端口號
quint16 port = ui->portEdit->text().toUInt();
//將服務(wù)器設(shè)置成監(jiān)聽狀態(tài)
//函數(shù)原型: bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
//功能:監(jiān)聽客戶端發(fā)來的連接請求
//參數(shù)1:要監(jiān)聽的主機地址,Any表示監(jiān)聽任意主機地址,也可以給定指定主機地址
//參數(shù)2:提供的端口號,如果是0:表示讓系統(tǒng)自動分配端口號
//返回值:bool,成功監(jiān)聽返回true,失敗返回false
if(server->listen(QHostAddress::Any,port) == true)
{
QMessageBox::information(this,"","服務(wù)器啟動成功");
}
else
{
QMessageBox::information(this,"","服務(wù)器啟動失敗");
}
//此時服務(wù)器已經(jīng)進入監(jiān)聽狀態(tài),如果有客戶端發(fā)送連接請求,該服務(wù)器就會自動發(fā)射一個newConnection信號
//那么我們可以將該信號連接到自定義的槽函數(shù)中處理新連接的套接字
connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
}
//處理newConnection信號的槽函數(shù)
void Widget::newConnection_slot()
{
qDebug() << "有客戶端連接了";
//獲取最新連接的客戶端套接字
//函數(shù)原型: virtual QTcpSocket *nextPendingConnection();
//功能:獲取最新連接客戶端的套接字
//參數(shù):無
//返回值:套接字指針
QTcpSocket *s = server->nextPendingConnection(); //獲取套接字
//將套接字放入到客戶端容器中
socketList.push_back(s); //尾插
//此時,客戶端與服務(wù)器已經(jīng)建立起來連接,如果有客戶端向服務(wù)器發(fā)來數(shù)據(jù),客戶端會自動發(fā)射一個readyRead信號
//我們可以在該信號對應(yīng)的槽函數(shù)中,讀取客戶端中的數(shù)據(jù)
connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
//關(guān)于readyRead信號對應(yīng)槽函數(shù)的實現(xiàn)
void Widget::readyRead_slot()
{
//移除無效客戶端
for(int i=0;i<socketList.count();i++)
{
//函數(shù)原型: SocketState state() const;
//功能:返回套接字狀態(tài)
//返回值:套接字狀態(tài),是個枚舉值,0表示無效連接
if(socketList.at(i)->state() == 0) //遍歷所有客戶端的狀態(tài)
{
socketList.removeAt(i); //將下標(biāo)為i的套接字從鏈表中移除
}
}
//遍歷客戶端套接字,尋找是哪個客戶端有數(shù)據(jù)待讀
for(int i=0;i<socketList.count();i++)
{
//函數(shù)原型:qint64 bytesAvailable() const override;
//功能:求出當(dāng)前套接字中待讀數(shù)據(jù)的個數(shù)
//參數(shù):無
//返回值:待讀數(shù)據(jù)的個數(shù)
if(socketList.at(i)->bytesAvailable() != 0)
{
//函數(shù)原型:QByteArray readAll()
//功能:讀取當(dāng)前套接字中的數(shù)據(jù)
//返回值:QByteArray讀取下來的數(shù)據(jù)
QByteArray msg = socketList.at(i)->readAll();
//將數(shù)據(jù)展示到ui界面上
ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
//將數(shù)據(jù)發(fā)送給所有客戶端
for(int j=0;j<socketList.count();j++)
{
//將數(shù)據(jù)寫入到所有客戶端套接字中
socketList.at(j) ->write(msg);
}
}
}
}
文章來源:http://www.zghlxwxcb.cn/news/detail-618295.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-618295.html
到了這里,關(guān)于【QT】Day4的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!