Qt live video software -- project practice (Day1)

Keywords: Qt server

1, Project requirements

Don't write it first. We'll add it when we're finished

2, Design ideas

It's late today. Just make a code record. It's all on paper and will be added later

3, Day 1 project diary

1. Today's summary:

I wrote half a server today,
Main functions
1) You can create a server using Tcp protocol, define the port yourself, and click the button to open the server
2) When a server is connected, the connected user can be displayed. Here is the random id number
3) When the client is disconnected, the list is refreshed. Only the online id and the number of online clients are displayed
4) After the client sends data, the message content broadcast is sent to all clients

Test: any network tool can be used. Here, you only need to act as a client.

2. Server interface


explain:
After starting the operation, you can enter the port number. After clicking start service, the button will be grayed out and port cannot be entered. After clicking close service, you will exit. The number of online clients will be displayed in real time. The login log is used to view the login records and is temporarily unavailable.
When a client is connected, the connection id is displayed. After disconnection, it is refreshed in real time.

3. Code structure


Note: tcpsocket is a class inherited from QTcpSocket
tcpsocket is a class inherited from QTcpServer
mymessage is a custom message sending class

1,mymessage.h

There's nothing to say, just encapsulate a message

#ifndef MYMESSAGE_H
#define MYMESSAGE_H

#include <QString>

enum MsgId{
    MSG_CLITEN_CONNECT = 0, //Connection message
    MSG_READ_BYTES,   //Read received messages
    MSG_CLIENT_CLOSE,   //Client shutdown message
};


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();
};

#endif // MYMESSAGE_H

2,mymessage.cpp

Implementation of some message functions

#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;
}

3,tcpsocket.h

It inherits from QTcpSocket and then rewrites some functions

#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
#include "mymessage.h"
#include <QDebug>

class TcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TcpSocket(QObject* parent = 0);

signals:
    void disconnected(int); //Send offline signal
    void messageToServer(MyMessage); //Send message to server

public slots:
    void datadisconnected(); //Used to process off-line signals
    void dataReceived();    //Used to process received client messages
};

#endif // TCPSOCKET_H

4,tcpsocket.cpp
#include "tcpsocket.h"

TcpSocket::TcpSocket(QObject *parent):
    QTcpSocket(parent)
{
    //I originally wanted to send the connection signal to the server here, but it was found that the port number and ip address could not be read when his state changed, so I put it in the socket in the room to send the message
//    connect(this,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(dataconnected()));
    //Connect the disconnection function / read function and the custom slot function
    connect(this,SIGNAL(disconnected()),this,SLOT(datadisconnected()));
    connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
}

void TcpSocket::datadisconnected()
{
    //- 1 will be sent after disconnection
    emit disconnected(this->socketDescriptor());
}

void TcpSocket::dataReceived()
{
    //Processing supervision signals
    while(this->bytesAvailable() > 0){
        char buf[1024];
        int length = bytesAvailable();
        this->read(buf,length);         //Read receive
        QString msgbuf = buf;
        //Convert it into a message and send it to the server
        MyMessage message(MSG_READ_BYTES,buf,length);
        emit messageToServer(message); //Transmit message signal
    }
}


5,tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QObject>
#include <QtNetwork>
#include <QTcpServer>
#include "tcpsocket.h"

class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit TcpServer(QObject* parent = 0,int port = 0);
    QList<TcpSocket*> tcpSocketList;//list container for storing client pointers
    QList<int> descriptorList;//It is used to compare the container of the client. It is used when deleting

protected:
    void incomingConnection(int socketDescriptor);//Overridden join function

signals:
    void msgToServer(MyMessage);//A signal used to send a message to main

public slots:
    void msgFromSocket(MyMessage);//Slot function used to process signals received from socket
    void tcpDisconnected(int);//Slot function to handle client disconnection
};

#endif // TCPSERVER_H

6,tcpserver.cpp
#include "tcpserver.h"

TcpServer::TcpServer(QObject *parent, int port):
    QTcpServer(parent)
{
    listen(QHostAddress::AnyIPv4,port); //Used to listen to ipv4 clients. port is passed in
}

void TcpServer::incomingConnection(int socketDescriptor)
{
    TcpSocket *tcpSocket = new TcpSocket(this);
    tcpSocket->setSocketDescriptor(socketDescriptor);
    //Send message to server interface
    QString msgbuf = QString::number(socketDescriptor);
    //QString msgbuf = tcpSocket->peerAddress().toString()+" "+QString::number(tcpSocket->peerPort());
    MyMessage message(MSG_CLITEN_CONNECT,msgbuf,msgbuf.length());
    //qDebug()<<msgbuf << " "<<socketDescriptor;
    emit msgToServer(message);//Send connection message
    connect(tcpSocket, SIGNAL(messageToServer(MyMessage)),
            this, SLOT(msgFromSocket(MyMessage)));
    connect(tcpSocket, SIGNAL(disconnected(int)),
            this, SLOT(tcpDisconnected(int)));
    //Put the socket pointer in the socket list
    tcpSocketList.append(tcpSocket);
    //Put his Descriptor in another container
    descriptorList.append(socketDescriptor);
}

void TcpServer::msgFromSocket(MyMessage message)
{
    emit msgToServer(message);
    //The following is to reply the same data to the client
    for(int i = 0; i < tcpSocketList.count(); i++)
    {
        QTcpSocket *temp = tcpSocketList.at(i);
        if(temp->write(message.getmsgbuf().toLatin1(), message.getlength()) != message.getlength())
        {
            continue;
        }
    }
}

void TcpServer::tcpDisconnected(int descriptor)
{
    //After disconnection, the descriptor will become - 1, so I don't know which is disconnected, so I can only judge by myself
    //Therefore, a qlist < int > is used to store. When it becomes - 1, it means that it is turned off
    for(int i = 0; i < tcpSocketList.count(); i++)
    {
        QTcpSocket *temp = tcpSocketList.at(i);
        if(temp->socketDescriptor() == descriptor)
        {
            temp->destroyed();
            tcpSocketList.removeAt(i);
            break;
        }
    }
    int close_descriptor = 0;
    int j = 0;
    //Compare the two containers to see which client is offline
    for(int i = 0; i < descriptorList.count(); i++){
        close_descriptor = descriptorList.value(i);
        for(j = 0; j < tcpSocketList.count(); j++){
            QTcpSocket *temp = tcpSocketList.at(j);
            if(close_descriptor == temp->socketDescriptor()){
                break;
            }
        }
        if(j == tcpSocketList.count()){
            //qDebug()<<close_descriptor << "is close";
            descriptorList.removeAt(i);
            break;
        }
    }
    //Send a message that the client is closed
    QString msgbuf = QString::number(close_descriptor);
    MyMessage message(MSG_CLIENT_CLOSE,msgbuf,msgbuf.length());
    emit msgToServer(message);
    return;
}

7,mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "tcpserver.h"
#include <QtNetwork>
#include <QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void deleteclientlist(int);//Used to clear the signal client list

private:
    Ui::MainWindow *ui;
    QTcpServer *tcpServer;
    int port;
    int online_num;

public slots:
    void RecvMsg(MyMessage);
private slots:
    void on_pushclose_clicked();
    void on_pushopen_clicked();
};
#endif // MAINWINDOW_H

8,mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "tcpserver.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("The server");
    ui->lineport->setText("8010");//The default port number is 8010
    ui->label_onlinenum->setText("0");//The default number of connections must be 0
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::deleteclientlist(int client_id)
{
    int row = 0;
    QString str = QString::number(client_id);
    QString line;
    while(row < ui->listusers->count()){
        line=ui->listusers->item(row)->text();
        if(str==line)
        {
            //Qdebug() < < "delete succeeded";
            ui->listusers->takeItem(row);
            break;
        }
        row++;
    }
}

void MainWindow::RecvMsg(MyMessage message)
{
    //qDebug()<<message.getmsgbuf().left(message.getlength());
    if(message.getmsgid() == MSG_CLITEN_CONNECT){
        ui->listusers->addItem(message.getmsgbuf().left(message.getlength()));
        ui->label_onlinenum->setText(QString::number(ui->listusers->count()));
    }else if(message.getmsgid() == MSG_READ_BYTES){
        //qDebug()<<message.getmsgbuf().left(message.getlength());
    }else if(message.getmsgid() == MSG_CLIENT_CLOSE){
        //After receiving the closing message, delete the id of the client. The message content is the id of the client
        this->deleteclientlist(message.getmsgbuf().toInt());
        //Update the label of online people
        ui->label_onlinenum->setText(QString::number(ui->listusers->count()));
    }
    return;
}


void MainWindow::on_pushclose_clicked()
{
    qApp->quit();
}

void MainWindow::on_pushopen_clicked()
{
    if(ui->lineport->text().isEmpty()){
        QMessageBox::warning(this, tr("warning!!"),
                             tr("please input you Port!"));
        return;
    }
    port = ui->lineport->text().toInt();
    tcpServer = new TcpServer(this, port);
    QObject::connect(tcpServer,SIGNAL(msgToServer(MyMessage)),this,SLOT(RecvMsg(MyMessage)));
    //The button cannot be clicked after the service is started
    ui->pushopen->setEnabled(false);
    ui->lineport->setEnabled(false);
    return;
}

4. Project documents

Download address

5. Effect display

1) You can create a server using Tcp protocol, define the port yourself, and click the button to open the server
2) When a server is connected, the connected user can be displayed. Here is the random id number
3) When the client is disconnected, the list is refreshed. Only the online id and the number of online clients are displayed
4) After the client sends data, the message content broadcast is sent to all clients
All have been realized, and the effects are as follows

4, End of record

Conclusion: it's a long way to go. I'll ask from top to bottom!!!

Posted by praeses on Wed, 03 Nov 2021 16:06:11 -0700