日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt视频直播软件--项目实战(Day4)

發布時間:2024/8/1 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt视频直播软件--项目实战(Day4) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第四天項目日記

1、今日總結

今天開始寫客戶端
1)先設計登錄界面
2)然后用線程開啟socket
3)用線程開的話可以實時獲取登錄的狀態
關于TCP我參考了這篇博文

2、設計思路

寫的時候試過在連接的時候用信號來處理連接狀態,但是發現在等待連接的過程中,ui的控件不會發生改變,說明ui的控件被阻塞了,所以tcp的連接用線程來寫,這樣就可以實現在界面中實時顯示連接狀態。

3、代碼說明

widget.ui


界面如圖所示
這里只用了一個界面,然后設計思路是:在登錄之前,只顯示上面的界面,登錄成功之后,只顯示下面的界面。
輸入用戶名密碼點擊登錄,先判斷服務器在不在線,如果在線的話就發送用戶名密碼,然后服務器對客戶端發過來的用戶名和密碼進行判斷,如果匹配了就會跳到下面的頁面,如果沒匹配就返回失敗原因

注冊的話也是先判斷有沒有連接上,如果連接上了,就發送注冊信息給服務器,如果沒連接上就顯示連接不到服務器。

兩個功能均未完全實現;

tcpthread.h (繼承自QThread)

#ifndef TCPTHREAD_H #define TCPTHREAD_H#include <QObject> #include <QTcpSocket> #include <QThread> #include <QDebug>class TcpThread : public QThread {Q_OBJECT public:explicit TcpThread(QObject *parent = 0);~TcpThread();void startThread(const QString& ip, int port);void stopThread();signals:void send_tcpmsg(QString);public:int m_iSendData;int m_iRecv_TimeOut;int reconnect_num;private:QTcpSocket* m_TcpSocket;bool m_isThreaStopped;bool m_isOkConect;QString m_QStrSocketIp;int m_nSockPort;QByteArray m_datagram;protected:virtual void run();private slots:void onConnect();void onDisConnect();void onReadMsg();void onSendTcp(QString); public slots: };#endif // TCPTHREAD_H

tcpthread.cpp

#include "tcpthread.h"TcpThread::TcpThread(QObject *parent) :QThread(parent) {m_TcpSocket = nullptr ;m_isThreaStopped = false;m_isOkConect = false;reconnect_num = 0; }TcpThread::~TcpThread() {m_isThreaStopped = true;quit();wait(); }void TcpThread::startThread(const QString &ip, int port) {m_QStrSocketIp = ip;m_nSockPort = port;m_isThreaStopped = false;start(); }void TcpThread::stopThread() {reconnect_num = 0;m_isThreaStopped = true; }void TcpThread::run() {bool b_recv_flag = false;emit send_tcpmsg("connecting");if (!m_TcpSocket){m_TcpSocket = new QTcpSocket(this);connect(m_TcpSocket, SIGNAL(readyRead()), this, SLOT(onReadMsg()),Qt::DirectConnection);//讓接受函數在run子線程中執行(發送者執行)connect(m_TcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));connect(m_TcpSocket, SIGNAL(disconnected()), this, SLOT(onDisConnect()));}while (!m_isThreaStopped){//檢測客戶端 socket指針是否為空if(b_recv_flag)msleep(100);if (!m_isOkConect){// 終止當前連接并重置套接字(立即關閉套接字,丟棄寫緩沖區中的任何掛起數據)m_TcpSocket->abort();m_TcpSocket->connectToHost(m_QStrSocketIp, m_nSockPort);//等待連接。。。延時三秒,三秒內連不上返回falsem_isOkConect = m_TcpSocket->waitForConnected(3000);m_iRecv_TimeOut = -1;reconnect_num++;}if (!m_isOkConect){msleep(1);if(reconnect_num <3){QString reconnect = "reconnect_"+QString::number(reconnect_num);emit send_tcpmsg(reconnect);continue;}else{emit send_tcpmsg("overtime");break;}}else{qDebug()<<"tcp_flag:"<<m_iRecv_TimeOut;onSendTcp("");}b_recv_flag = m_TcpSocket->waitForReadyRead(100);if (b_recv_flag){m_iRecv_TimeOut = 0;}else{m_iRecv_TimeOut++;if(m_iRecv_TimeOut>150) m_iRecv_TimeOut=150;}if(m_iRecv_TimeOut >= 150){m_iRecv_TimeOut = -1;m_TcpSocket->disconnectFromHost();}}qDebug()<<"exit_5";m_TcpSocket->disconnectFromHost();qDebug()<<"exit_6";}void TcpThread::onConnect() {reconnect_num = 0;emit send_tcpmsg("connect"); }void TcpThread::onDisConnect() {//socket一旦斷開則自動進入這個槽函數//通過把 m_isOkConect 設為false,在socket線程的run函數中將會重新連接主機qDebug()<<"socket is disconnect!"<<endl;m_isOkConect = false;m_iRecv_TimeOut = -1;emit send_tcpmsg("disconnect"); }void TcpThread::onReadMsg() {if(m_TcpSocket->bytesAvailable() <= 0){// 判定連接失敗m_TcpSocket->disconnectFromHost();}while (m_TcpSocket->bytesAvailable() > 0){// 接收數據m_datagram.clear();m_datagram.resize(m_TcpSocket->bytesAvailable());m_TcpSocket->read(m_datagram.data(), m_datagram.size());QString str_tcp_receive = QString::fromLocal8Bit(m_datagram);qDebug()<<str_tcp_receive;msleep(100);} }void TcpThread::onSendTcp(QString str_info) {if((!m_TcpSocket)||m_TcpSocket->state()!=QAbstractSocket::ConnectedState)return;m_iSendData = m_TcpSocket->write(str_info.toStdString().c_str(), strlen(str_info.toStdString().c_str()));m_TcpSocket->flush();if (m_iSendData < 0){m_TcpSocket->disconnectFromHost();return;}msleep(1000); }

widget.h

#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMessageBox> #include <QDebug> #include "tcpthread.h" #include "mymessage.h"namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();void Logic_Init();//登錄初始化void User_Init();//使用界面初始化void connectToServer(); //用連接服務器public slots:void connect_state(QString); //用來控制連接狀態void connect_success(); //用來表示連接成功private slots:void on_radioshow_clicked(bool checked); //用來顯示密碼和隱藏密碼void on_pushlogic_clicked();//用來登錄void on_pushquit_clicked();//用來退出private:Ui::Widget *ui;TcpThread *tcpThread;//用來啟動socket線程 // bool status;QString userName; //賬號QString passWard; //密碼signals:void connect_enable(); //連接};#endif // WIDGET_H

widget.cpp

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {connect(this,SIGNAL(connect_enable()),this,SLOT(connect_success()));ui->setupUi(this);tcpThread = nullptr; // status = false;Logic_Init(); }Widget::~Widget() {delete ui; }void Widget::Logic_Init() {this->setWindowTitle("登錄/注冊");ui->linepswd->show();ui->lineUser->show();ui->radioshow->show();ui->pushlogic->show();ui->pushregister->show();ui->linepswd->setEchoMode(QLineEdit::Password);ui->pushAdd->hide();ui->pushCreate->hide();ui->listView->hide();ui->pushquit->hide(); }void Widget::User_Init() {this->setWindowTitle("云木直播平臺");ui->linepswd->hide();ui->lineUser->hide();ui->radioshow->hide();ui->pushlogic->hide();ui->pushregister->hide();ui->label->hide();ui->label_2->hide();ui->label_3->hide();ui->pushAdd->show();ui->pushCreate->show();ui->listView->show();ui->pushquit->show(); }void Widget::connectToServer() {QString Address_Ip = "127.0.0.1";int port = 8010;if(!tcpThread){tcpThread = new TcpThread;QObject::connect(tcpThread,SIGNAL(send_tcpmsg(QString)),this,SLOT(connect_state(QString)));}tcpThread->startThread(Address_Ip,port); }void Widget::connect_state(QString message) {qDebug()<<message;if(message == "connecting") {ui->label_connect_state->setText("連接中...");}else if(message == "connect"){ui->label_connect_state->clear();emit connect_enable();}else if(message == "disconnect"){tcpThread->stopThread();}else if(message == "overtime"){QMessageBox::warning(NULL,tr("無法連接"),tr("無法連接請稍后再試"));ui->label_connect_state->clear();tcpThread->stopThread();}else if(message.left(9) == "reconnect"){QString text = "第"+message.right(1)+"次重連中";ui->label_connect_state->setText(text);} }void Widget::connect_success() {QString msgbuf = userName+" "+ passWard;MyMessage mymsg(MSG_LOGIC,msgbuf,msgbuf.length());qDebug()<<mymsg.toString();tcpThread->send_tcpmsg(mymsg.toString());User_Init(); }void Widget::on_radioshow_clicked(bool checked) {if(checked){ui->linepswd->setEchoMode(QLineEdit::Normal);}else{ui->linepswd->setEchoMode(QLineEdit::Password);} }void Widget::on_pushlogic_clicked() {if(ui->lineUser->text().isEmpty()){QMessageBox::warning(NULL,tr("輸入錯誤"),tr("賬號不能為空"));return;}if(ui->linepswd->text().isEmpty()){QMessageBox::warning(NULL,tr("輸入錯誤"),tr("密碼不能為空"));return;}userName = ui->lineUser->text();passWard = ui->linepswd->text();//連接connectToServer(); }void Widget::on_pushquit_clicked() {tcpThread->stopThread();QMessageBox::about(NULL,tr("退出"),tr("點擊退出"));this->close(); }

mymessage.h

#ifndef MYMESSAGE_H #define MYMESSAGE_H#include <QString>enum MsgId{MSG_CLITEN_CONNECT = 0, //連接消息MSG_READ_BYTES, //讀取接收到的消息MSG_CLIENT_CLOSE, //客戶端關閉的消息MSG_LOGIC, //客戶端登錄消息 };class MyMessage {enum MsgId msgid;QString msgbuf;int length; public:MyMessage();MyMessage(MsgId msgid,QString msgbuf,int length);void setmsgid(MsgId msgid);void setmsgbuf(QString msgbuf);void setlength(int length);int getmsgid();QString getmsgbuf();int getlength();QString toString(); };#endif // MYMESSAGE_H

mymessage.cpp

#include "mymessage.h"MyMessage::MyMessage() {}MyMessage::MyMessage(MsgId msgid, QString msgbuf, int length) {this->msgid = msgid;this->msgbuf = msgbuf;this->length = length; }void MyMessage::setmsgid(MsgId msgid) {this->msgid = msgid; }void MyMessage::setmsgbuf(QString msgbuf) {this->msgbuf = msgbuf; }void MyMessage::setlength(int length) {this->length = length; }int MyMessage::getmsgid() {return msgid; }QString MyMessage::getmsgbuf() {return msgbuf; }int MyMessage::getlength() {return length; }QString MyMessage::toString() {QString send_msg = QString::number(msgid)+"|"+msgbuf;return send_msg; }

4、項目文件

源代碼鏈接接.

5、效果展示

測試如下

1、先測試賬號密碼不輸入的情況下,提示信息
然后測試密碼顯示和隱藏
2、測試不開啟服務器的情況下登錄超時的情況
連接次數三次,每次超時時間為3s,三次結束之后提示連接不到服務器
連接過程中有提示,點擊確定之后情況提示

3、測試連接過程中開啟服務器,自動連接成功(密碼驗證還沒有寫)
只測試界面跳轉,跳轉之后點擊退出,客戶端退出 退出之后服務器顯示的在線列表自動會清掉

6、每日總結

今日學會使用 QThread里面創建 QTcpSocket
為了讓連接過程中顯示連接狀態,真的是廢了很大的功夫。。。
就這樣慢慢成長吧。

另外,要考慮在消息傳遞的過程中使用 json 格式進行封裝一下,所以可能要調研一下 QJson

堅持就是勝利!!!!!!

總結

以上是生活随笔為你收集整理的Qt视频直播软件--项目实战(Day4)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。