Small chat software based on C++/qml (including source code)

https://www.programmersought.com/article/74196226714/

 

Server source code

 

main.qml

import  QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import Server_support 1.0
Window{
 
 
    id:window
    width:800
    height:550
 
    Rectangle{
        width:800
        height:550
        gradient: Gradient {//Gradient attribute
                         GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
                position: 0.0; color: "white"
            }
            GradientStop{
                position: 1.0; color: "pink"
            }
        }
    }
    visible:true
    ListView{
        add: Transition {
                         //Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
            NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
        }
        id:listview
        anchors.top: parent.top
        anchors.bottom: bottomrect.top
        anchors.left:parent.left
        anchors.right:parent.right
                 //anchors' object is either a sibling node (provide id)
                 //Either the child node (parent)
                 delegate:Component{ //here delegate: must be followed by Component
            Rectangle{
                width:550
                height:label1.height+20
                opacity: 0.8
                // color:"black"
                BorderImage{
                                         //Chat bubble
                    id:qipao
                    source:"pao.png"
                    width:label1.width+30
                    height:label1.height<=30?30:label1.height+5
                    //  width:20
                    border.left: 10
                    border.right: 10
                    border.top:10
                    border.bottom:10
                    x:parent.width-width
                    Text{
                        id:label1
                        /*************
                                                                                           Here is the focus of the variable size chat bubble
                                                                                           According to the length of the obtained value and the pixels occupied by each word
                                            *************/
                        width:label1.text.length<=10?label1.text.length*12:120
                        font.pixelSize: 12
                        anchors.centerIn:parent
                        anchors.leftMargin:10
                                                 wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
                        text:detail
                    }
                }
            }
        }
        model:ListModel{
            id:listmodel
            ListElement{
                detail:"This is Server."
 
            }
        }
    }
         //Right
    Rectangle {
        id:message3
 
        border.color: "black"
        anchors.right: parent.right
        anchors.top: window.top
        height:510
        width:window.width*0.3
                 gradient: Gradient {//Gradient attribute
                         GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
                position: 0.0; color: "red"
            }
            GradientStop{
                position: 1.0; color: "blue"
            }
        }
    }
 
    Label{
        id:label2;
        text:"value";
        anchors.top: message3.top
        x:570
    }
         //Bottom
    Rectangle{
        height: 40
        width: 550
        anchors.bottom: parent.bottom
        id:bottomrect
        Row{
            TextField{
                id:textfield
                                 placeholderText: "input content"
                height:bottomrect.height
                width:window.width*0.7
            }
        }
 
       Button{
            id:button1
            text:"Send"
            x:560
            anchors.top: message3.bottom
            onClicked: {
 
                listmodel.append({"detail":textfield.text})
                var result = textfield.text
                server.sendMessage(result);
                                 //textfield.text='' Clear the input box after sending the message
            }
        }
        Button
        {
            id:button2
            text:"Connect"
            anchors.left: button1.right
            onClicked:
            {
                label2.text=server.mystring
                server.connect_client();
            }
                         //Connect the signal to qml
            Connections{
                target:server;
                onMystringChanged:label2.text = str;
            }
        }
        Button
        {
            id:button3
            text:"Quit"
            anchors.left: button2.right
            onClicked:
            {
                window.close();
            }
        }
    }
    Server
    {
        id:server
    }
         //Receive the message on the left
    //    Label{
    //        id:recv_message_window;
    //        text:"recv_message";
    //        width:275
    //        height:550
    //        y:20
    //       Button
    //       {
    //           id:button4
    //           text:"recvmsg"
    //           x:750
    //           y:490
 
    //           //anchors.right: window.right
    //           onClicked:
    //           {
    //               recv_message_window.text=server.message
    //           }
    //           Connections{
    //                target:server;
    //                onMessageChanged: recv_message_window.text = str;
    //                      }
    //        }
    //    }
    ListView{
        width:200
        height:550
        add: Transition {
                         //Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
            NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
        }
        id:listview2
        anchors.top: parent.top
        anchors.bottom: bottomrect.top
        anchors.left:parent.left
        anchors.right:parent.right
                 //anchors' object is either a sibling node (provide id)
                 //Either the child node (parent)
                 delegate:Component{ //here delegate: must be followed by Component
            Rectangle{
                width:200
                height:label3.height
                opacity: 0.8
                BorderImage{
                                         //Chat bubble
                    id:qipao
                    source:"pao.png"
                    width:label3.width+30
                    height:label3.height<=30?30:label3.height+5
                    //  width:20
                    border.left: 10
                    border.right: 10
                    border.top:10
                    border.bottom:10
                    x:parent.width-width
                    Text{
                        id:label3
                        /*************
                                                   Here is the focus of the variable size chat bubble
                                                   According to the length of the obtained value and the pixels occupied by each word
                         *************/
                        width:label3.text.length<=10?label3.text.length*12:120
                        font.pixelSize: 12
                        anchors.centerIn:parent
                        anchors.leftMargin:10
                                                 wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
                        text:detail
                    }
                }
            }
        }
        model:ListModel{
            id:listmodel2
            ListElement{
                detail:""
            }
        }
    }
    Rectangle{
        anchors.top: parent.top
        id:bottomrect2
        Row{
            Text{
                id:textfield2
                height:bottomrect2.height
                width:window.width*0.7
               // anchors.top : ListView.top
            }
        }
    }
    Button
    {
        id:button4
        text:"recvmsg"
        x:720
        y:510
        anchors.left: button3.right
        onClicked:
        {
            listmodel2.append({"detail":textfield2.text})
            textfield2.text=server.message
        }
        Connections{
            target:server;
            onMessageChanged: textfield2.text = str;
        }
    }
}
server.cpp

#include "server.h"
static SOCKET slisten;
static SOCKET sClient;
Server::Server(QObject *parent):QObject(parent)
{
    m_pstring = new QString;
    recv_data = new QString;
    send_data = new QString;
}
Server::~Server()
{
    delete this->m_pstring;
}
 
 
QString Server::getString()
{
    setString("waiting connect...");
    return *(this->m_pstring);
}
 
 
void Server::setString(QString string){
    *(this->m_pstring)=string;
         emit mystringChanged(string);//Send signal
}
 
 
QString Server::message()
{
    return *recv_data;
}
void Server::setMessage(QString string)
{
    *recv_data=string;
}
void Server::sendMessage(QString string)
{
    *send_data = string;
    qDebug()<<*send_data;
}
 
 
void Server::connect_client()
{
    WORD sockVersion = MAKEWORD(2, 2);
    WSADATA wsaData;
    if (WSAStartup(sockVersion, &wsaData) != 0)
    {
        exit(0);
    }
    slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (slisten == INVALID_SOCKET)
    {
        cout<<"socket error !"<<endl;
        exit(0);
    }
    else
        cout<<"socket suceess."<<endl;
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8080);
    sin.sin_addr.S_un.S_addr = INADDR_ANY;
    if (::bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
    {
        cout <<  "bind error !" << endl;
    }
    else
        cout<<"bind success."<<endl;
    if (listen(slisten, 5) == SOCKET_ERROR)
    {
        cout << "listen error !"<< endl;
        exit(0);
    }
    else
        cout<<"listen succeed."<<endl;
 
    start_thread1();
}
 
 
 
void Server::recvsend_message()
{
    sockaddr_in remoteAddr;
    int nAddrlen = sizeof(remoteAddr);
    int  count=0;
    start_thread2();
 
    while(true)
    {
        count++;
        if(count==1)
        {
            cout<<"wating connect..."<<endl;
        }
        sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
        if(count==1)
        {
            cout<<"accept one client."<<endl;
        }
        if (sClient == INVALID_SOCKET)
        {
            printf("accept error !");
            continue;
        }
        if(count == 1)
        {
            cout <<"accepted a connection:"<< inet_ntoa(remoteAddr.sin_addr) << endl;
        }
        cout << inet_ntoa(remoteAddr.sin_addr)<<":";
        send_news();
 
    }
    closesocket(sClient);
    WSACleanup();
}
 
 
void Server::recv_news()
{
    char revData[255];
    int ret = 0;
    int count = 0;
    while(true)
    {
        ret = recv(sClient, revData, 255, 0);
        count++;
        if(count == 1)
        {
            cout<<"recv success!"<<endl;
        }
        if (ret > 0)
        {
            revData[ret] = '\0';
            *recv_data = QString(QLatin1String(revData));
            qDebug()<<*recv_data;
            emit messageChanged(*recv_data);
            cout<<"recv a massgae:"<<revData<<endl;
        }
    }
}
void Server::send_news()
{
 
    char sendbuffer[255];
    while(true)
    {
        if((*send_data).size() > 0)
        {
            QByteArray buffer = (*send_data).toUtf8();
            char *sendData = buffer.data();
 
            strcpy(sendbuffer,sendData);
            sendbuffer[strlen(sendbuffer)]='\0';
            cout<<sendbuffer<<endl;
            send(sClient, sendbuffer, strlen(sendbuffer), 0);
            *send_data = "\0";
            memset(sendbuffer,0,255);
        }
    }
}
 
 
 
void Server::start_thread1()
{
    std::thread t1(&Server::thread1,this);
    t1.detach();
}
void* Server::thread1(void *this_)
{
    Server *_this = (Server*) this_;
    _this->recvsend_message();
    return _this;
}
 
void Server::start_thread2()
{
    std::thread t2(&Server::thread2,this);
    t2.detach();
}
 
void* Server::thread2(void *this_)
{
    Server *_this = (Server*) this_;
    _this->recv_news();
    return _this;
}
 
 
 
 
void Server::start_thread3()
{
    std::thread t3(&Server::thread3,this);
    t3.detach();
}
void* Server::thread3(void *this_)
{
    Server *_this = (Server*) this_;
    _this->send_news();
    return _this;
}
server.h

#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include<QString>
#include<qdebug.h>
#include<iostream>
#include<windows.h>
#include<thread>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
class Server : public QObject
{
    Q_OBJECT
         //Exposed to QML attributes
    Q_PROPERTY(QString mystring READ getString WRITE setString NOTIFY mystringChanged)
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
    explicit Server(QObject *parent = 0);
         Q_INVOKABLE QString getString(); //Q_INVOCABLE is exposed to QML
    Q_INVOKABLE void setString(QString string);
    Q_INVOKABLE QString message();
 
    Q_INVOKABLE void setMessage(QString string);
    Q_INVOKABLE void sendMessage(QString string);
 
    ~Server();
    Q_INVOKABLE void connect_client();
    void recvsend_message();
    void recv_news();
    void send_news();
    void start_thread1();
    void start_thread2();
    void start_thread3();
    static void* thread1(void* this_);
    static void* thread2(void* this_);
    static void* thread3(void* this_);
signals:
         void mystringChanged(QString value); //signal
    void  messageChanged(QString str);
public:
    QString *m_pstring;
    QString *recv_data;
    QString *send_data;
};
#endif // SERVER_H
main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include<QtQml>
#include"server.h"
 
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
         //Register to QML
    qmlRegisterType<Server>("Server_support",1,0,"Server");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
 
    return app.exec();
}
 

Client source code

main.qml

import  QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import RegisterClient 1.0
Window{
    id:window
 
    width:800
    height:550
 
    Rectangle{
        width:800
        height:550
                 gradient: Gradient {//Gradient attribute
                         GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
                position: 0.0; color: "white"
            }
            GradientStop{
                position: 1.0; color: "pink"
            }
        }
    }
    visible:true
    ListView{
        add: Transition {
                         //Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
            NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
        }
        id:listview
        anchors.top: parent.top
        anchors.bottom: bottomrect.top
        anchors.left:parent.left
        anchors.right:parent.right
                 //anchors' object is either a sibling node (provide id)
                 //Either the child node (parent)
                 delegate:Component{ //here delegate: must be followed by Component
            Rectangle{
                width:550
                height:label1.height+20
                opacity: 0.8
                // color:"black"
                BorderImage{
                                         //Chat bubble
                    id:qipao
                    source:"pao.png"
                    width:label1.width+30
                    height:label1.height<=30?30:label1.height+5
                    //  width:20
                    border.left: 10
                    border.right: 10
                    border.top:10
                    border.bottom:10
                    x:parent.width-width
                    Text{
                        id:label1
                        /*************
                                                                                           Here is the focus of the variable size chat bubble
                                                                                           According to the length of the acquired value and the pixels occupied by each word
                                            *************/
                        width:label1.text.length<=10?label1.text.length*12:120
                        font.pixelSize: 12
                        anchors.centerIn:parent
                        anchors.leftMargin:10
                                                 wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
                        text:detail
                    }
                }
            }
        }
        model:ListModel{
            id:listmodel
            ListElement{
                detail:"This is Client."
 
            }
        }
    }
         //Right
    Rectangle {
        id:message3
 
        border.color: "black"
        anchors.right: parent.right
        anchors.top: window.top
        height:510
        width:window.width*0.3
                 gradient: Gradient {//Gradient attribute
                         GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right
                position: 0.0; color: "red"
            }
            GradientStop{
                position: 1.0; color: "blue"
            }
        }
    }
 
    Label{
        id:label2;
        text:"value";
        anchors.top: message3.top
        x:570
    }
         //Bottom
    Rectangle{
        height: 40
        width: 550
        anchors.bottom: parent.bottom
        id:bottomrect
        Row{
            TextField{
                id:textfield
                                 placeholderText: "input content"
                height:bottomrect.height
                width:window.width*0.7
 
            }
        }
        Button{
            id:button1
            text:"Send"
            x:560
            anchors.top: message3.bottom
            onClicked: {
                listmodel.append({"detail":textfield.text})
                client.obtain_message(textfield.text);
                //textfield.text=''
            }
        }
        Client
        {
            id:client
        }
        Button
        {
            id:button2
            text:"Connect"
            anchors.left: button1.right
            onClicked:
            {
                label2.text=client.mystring
                client.connect_server();
                //client.communication();
            }
            //Connect the signal to qml
            Connections{
                target:client;
                onMystringChanged:label2.text = str;
                                 //The value here is the parameter in the signal function
            }
        }
        Button
        {
            id:button3
            text:"Quit"
            anchors.left: button2.right
            onClicked:
            {
                window.close();
            }
        }
 
    }
 
    ListView{
        width:200
        height:550
        add: Transition {
                         //Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
            NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
        }
        id:listview2
        anchors.top: parent.top
        anchors.bottom: bottomrect.top
        anchors.left:parent.left
        anchors.right:parent.right
                 //anchors' object is either a sibling node (provide id)
                 //Either the child node (parent)
                 delegate:Component{ //here delegate: must be followed by Component
            Rectangle{
                width:200
                height:label3.height
                opacity: 0.8
                BorderImage{
                                         //Chat bubble
                    id:qipao
                    source:"pao.png"
                    width:label3.width+30
                    height:label3.height<=30?30:label3.height+5
                    //  width:20
                    border.left: 10
                    border.right: 10
                    border.top:10
                    border.bottom:10
                    x:parent.width-width
                    Text{
                        id:label3
                        /*************
                                                           Here is the focus of the variable size chat bubble
                                                           According to the length of the obtained value and the pixels occupied by each word
                             *************/
                        width:label3.text.length<=10?label3.text.length*12:120
                        font.pixelSize: 12
                        anchors.centerIn:parent
                        anchors.leftMargin:10
                                                 wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
                        text:detail
                    }
                }
            }
        }
        model:ListModel{
            id:listmodel2
            ListElement{
                detail:""
            }
        }
    }
    Rectangle{
        anchors.top: parent.top
        id:bottomrect2
        Row{
            Text{
                id:textfield2
                height:bottomrect2.height
                width:window.width*0.7
                // anchors.top : ListView.top
            }
        }
    }
    Button
    {
        id:button4
        text:"recvmsg"
        x:720
        y:510
        anchors.left: button3.right
        onClicked:
        {
            listmodel2.append({"detail":textfield2.text})
            textfield2.text=client.message
        }
        Connections{
            target:client;
            onMessageChanged: textfield2.text = str;
        }
    }
 
 
 
}
/*
Window {
    width:200
    height: 100
    visible: true
    Button{
        id:btn1;
        height:20;
        width:60;
        text:"button";
        onClicked: {
                         //qml operation c++
            //btn1.text=myobj.mystring;
            label1.text = myobj.mystring;
        }
    }
    Label{
        id:label1;
                 text: "Initial value";
        anchors.left:btn1.right;
         //Create an object anchors.leftMargin: 12;
    }
    MyClassType
    {
         id:myobj;
    }
         //Connect the signal to qml
    Connections{
        target:myobj;
        onMystringChanged:label1.text=value;
                 //The value here is the parameter in the signal function
    }
}*/
client.cpp

#include"client.h"
static SOCKET sclient;
 
client::client(QObject *parent)
    :QObject(parent)
{
    this->m_pstring = new QString;
    this->send_data = new QString;
    this->recv_data = new QString;
}
 
client::~client()
{
    delete this->m_pstring;
    delete this->send_data;
    delete this->recv_data;
}
 
QString client::get_send_data()
{
    return *recv_data;
}
 
QString client::getString()
{
    setString("connect succeed...");
    return *(this->m_pstring);
}
void client::setString(QString string)
{
    *(this->m_pstring)=string;
         emit mystringChanged(string);//Send signal
}
 
 
void client::setMessage(QString string)
{
    *recv_data=string;
}
void client::sendMessage(QString string)
{
    *send_data = string;
    qDebug()<<*send_data;
}
 
 
void client::obtain_message(QString string)
{
    *send_data = string;
    qDebug()<<*send_data;
}
 
void client::connect_server()
{
    WORD sockVersion = MAKEWORD(2, 2);
    WSADATA data;
    if (WSAStartup(sockVersion, &data) != 0)
    {
        exit(0);
    }
    sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sclient == INVALID_SOCKET)
    {
        printf("invalid socket!");
        exit(0);
    }
    sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(8080);
    serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    if (::connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
    {
        printf("connect error !");
        closesocket(sclient);
        exit(0);
    }
    cout<<"connect succeed..."<<endl;
 
    start_thread1();
}
 
 
void client::communication()
{
    /*
         Create a separate thread for recv outside the loop
         Send messages in a loop
    */
    start_thread2();
     char sendData[255];
    while(true)
    {
        //cout<<"sendmessage:";
       // cout<<"!!!!!!!!!!!!!!!!!!!!!!"<<endl;
        if( (*send_data).size() > 0)
        {
            QByteArray buffer =(*send_data).toUtf8();
            char *p =buffer.data();
            strcpy(sendData,p);
            sendData[strlen(sendData)]='\0';
            cout<<sendData<<endl;
            send(sclient, sendData, strlen(sendData), 0);
            *send_data = "\0";
            memset(sendData,0,strlen(sendData));
        }
    }
 
    closesocket(sclient);
    WSACleanup();
}
 
QString client::message()
{
    return *recv_data;
}
void client::recv_news()
{
    char recData[255];
    int ret = 0;
    int count = 0;
    while(true)
    {
        cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
        ret = recv(sclient, recData, 255, 0);
        count++;
        if(count == 1)
        {
            cout<<"recv success!"<<endl;
        }
        if (ret>0)
        {
            recData[ret] = '\0';
            cout<<"recv a messgae:"<<recData<<endl;
            *recv_data = QString(QLatin1String(recData));
            emit messageChanged(*recv_data);
        }
        *recv_data="\0";
        memset(recData,0,255);
    }
}
 
void client::send_news()
{
    char sendData[255];
    //char sendData[]="This client ,hello server";
    //cout<<"!!!!!!!!!!!!!!!!!!!!!!"<<endl;
    if((*send_data).size() > 0)
    {
        QByteArray buffer =(*send_data).toUtf8();
        char *p =buffer.data();
        strcpy(sendData,p);
        sendData[strlen(sendData)]='\0';
        cout<<sendData<<endl;
        send(sclient, sendData, strlen(sendData), 0);
        //cout<<"Now,send the message to server."<<endl;
        *send_data = '\0';
        memset(sendData,0,strlen(sendData));
    }
 
}
 
void client::start_thread1()
{
    cout<<"start communicate."<<endl;
    std::thread t(&client::thread1,this);
    t.detach();
}
 
void* client::thread1(void* _this)
{
    client* p = (client*) _this;
    p->communication();
    return p;
}
 
 
void client::start_thread2()
{
    std::thread t(&client::thread2,this);
    t.detach();
}
void* client::thread2(void* _this)
{
    client*p = (client*) _this;
    p->recv_news();
    return p;
}
 
 
void client::start_thread3()
{
    std::thread t(&client::thread3,this);
    t.detach();
}
void* client::thread3(void* _this)
{
    client*p = (client*) _this;
    p->send_news();
    return p;
}
 
client.h

#ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include<QString>
#include<Qtimer.h>
#include<thread>
#include<Windows.h>
#include<qdebug.h>
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
using namespace std;
class client : public QObject
{
    Q_OBJECT
         //Exposed to QML attributes
    Q_PROPERTY(QString mystring READ getString WRITE setString NOTIFY mystringChanged)
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
    explicit client(QObject *parent = 0);
    ~client();
         Q_INVOKABLE QString getString(); //Q_INVOCABLE is exposed to QML
    Q_INVOKABLE void setString(QString string);
    Q_INVOKABLE QString message();
 
 
    Q_INVOKABLE void setMessage(QString string);
    Q_INVOKABLE void sendMessage(QString string);
 
    Q_INVOKABLE void obtain_message(QString str);
    Q_INVOKABLE QString get_send_data();
    void communication();
    void recv_news();
    void send_news();
signals:
         void mystringChanged(QString value); //signal
    void  messageChanged(QString str);
public slots:    
    Q_INVOKABLE void connect_server();
    static void*thread1(void*);
    static void*thread2(void*);
    static void*thread3(void*);
    void start_thread1();
    void start_thread2();
    void start_thread3();
public:
    QString * m_pstring;
    QString *send_data;
    QString *recv_data;
};
#endif // MYCLASS_H
main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include"client.h"
#include<QtQml>
 
 
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    qmlRegisterType<client>("RegisterClient",1,0,"Client");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
 
    return app.exec();
}
 
 

How to use the chat software:
1. After running Server and Client, first start the server and click Connect, then click the client Connect.
2. When the prompt on the upper right becomes waiting connect... and connect succeed, you can achieve duplex sending and receiving of messages.


ps: The upper left corner shows the real-time message. Click the recvmsg button to record the current message and display the message in the box.

Effect picture





Note: The chat box and the icon material can be selected arbitrarily

上一篇:【转载】 P2P(打洞)方案 及webrtc实现


下一篇:持续交付一:从开发到上线的环境