• C++ Qt多线程 TcpSocket服务器实例


    服务器:
    incomming
    incomming.pro
    #-------------------------------------------------
    #
    # Project created by QtCreator 2016-04-08T09:25:22
    #
    #-------------------------------------------------
    
    
    QT       += core gui
    QT        +=network
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    
    TARGET = incomming
    TEMPLATE = app
    
    
    
    
    SOURCES += main.cpp
            mainwindow.cpp 
        myserver.cpp 
        socketthread.cpp 
        mytcpsocket.cpp
    
    
    HEADERS  += mainwindow.h 
        myserver.h 
        socketthread.h 
        mytcpsocket.h
    
    
    FORMS    += mainwindow.ui
    
    
    
    
    mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    
    #include <QMainWindow>
    class QTcpSocket;
    class myserver;
    namespace Ui {
    class MainWindow;
    }
    
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    private:
      myserver * server;
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    
    private:
        Ui::MainWindow *ui;
    };
    
    
    #endif // MAINWINDOW_H
    
    
    
    myserver.h
    #ifndef MYSERVER
    #define MYSERVER
    #include<QObject>
    #include<QTcpServer>
    #include<QWidget>
    class myserver :public QTcpServer{
        Q_OBJECT
    public:
        myserver(QWidget * parent);
    protected:
        virtual void incomingConnection(qintptr socketDescriptor);
    
    
    };
    //|定义的结束 必须加;
    #endif // MYSERVER
    
    
    
    
    mytcpsocket.h
    #ifndef MYTCPSOCKET
    #define MYTCPSOCKET
    #include<QTcpSocket>
    
    
    class mytcpsocket :public QTcpSocket
    {
        Q_OBJECT
    public:
        mytcpsocket(QWidget * parent,qintptr p);
    private slots:
        void on_discon();
    
    
    public:
        void on_connected();
    
    
    };
    #endif // MYTCPSOCKET
    
    
    
    
    socketthread.h
    
    
    #ifndef SOCKETTHREAD
    #define SOCKETTHREAD
    #include<QThread>
    #include<QTcpSocket>
    #include<QWidget>
    class mytcpsocket;
    class socketThread :public QThread
    {
    private:
        qintptr ptr;
        mytcpsocket * socket;
    public:
        socketThread(QWidget * parent,qintptr p);
    protected:
        virtual void run();
    
    
    
    
    };
    #endif // SOCKETTHREAD
    
    
    
    
    mainwindow.cpp
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include"myserver.h"
    #include<QHostAddress>
    
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        this->server=new myserver(this);
        this->server->listen(QHostAddress::LocalHost,520);
    }
    
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    myserver.cpp
    #include"myserver.h"
    #include<QMessageBox>
    #include"mytcpsocket.h"
    #include"socketthread.h"
    myserver::myserver(QWidget * parent):QTcpServer(parent){
    
    
    }
    void myserver::incomingConnection(qintptr socketDescriptor)
    {
        QMessageBox::about(0,"提示","有新连接");
         socketThread * thread=new socketThread(0,socketDescriptor);
        thread->start();
    
    
        /*
        mytcpsocket * socket=new mytcpsocket(0,socketDescriptor);
        QThread * thread=new QThread();
        socket->moveToThread(thread);
        thread->start();
        */
    
    
    
    
    }
    
    
    mytcpsocket.cpp
    #include"mytcpsocket.h"
    #include<QByteArray>
    #include<QDataStream>
    #include<QString>
    #include<QMessageBox>
    #include<QDebug>
    mytcpsocket::mytcpsocket(QWidget *parent,qintptr p):QTcpSocket(0)
    {
    
    
      //connect(this,SIGNAL(),this,SLOT(on_connected()));
        this->setSocketDescriptor(p);
        this->on_connected();
     this->connect(this,SIGNAL(disconnected()),this,SLOT(on_discon()));
    
    
    }
    void mytcpsocket::on_connected()
    {
    
    
        QByteArray arr;
        QDataStream dts(&arr,QIODevice::WriteOnly);
        dts<<QString("这是数据");
        this->write(arr);
        //QMessageBox::about(0,"x","发送成功!");
        qDebug()<<"发送成功";
    
    
    }
    void mytcpsocket::on_discon()
    {
        qDebug()<<"有一个客户端断开!";
    }
    
    
    socketthread.cpp
    #include"socketthread.h"
    #include<QString>
    #include<QByteArray>
    #include<QDataStream>
    #include<QMessageBox>
    #include<QDebug>
    #include"mytcpsocket.h"
    socketThread::socketThread(QWidget *parent,qintptr p):QThread(parent)
    {
    
    
        qDebug()<<"QThread构造函数依然在 旧线程";
        this->ptr=p;
    }
    
    
    void socketThread::run(){
    
    
        /*1.QObject->moveToThread(Thread *)会把一个Qt对象移动到一个新线程中运行 默认在run()中调用了 exec()这样 run()执行完后不会
         * 直接关闭 线程 还会让它 进入消息循环 直到调用了 结束 槽
         * 2.QtcpSocket 的write()函数是异步的 也就是 调用了 后不会立即 发送数据,它会直接往下执行 直到run()的尾部,如果run()没有
         * 调用exec()进行消息循环等待,那么 这个线程 直接就结束了,不会再发送。(发送数据失败)
         *3.如果在run()中调用了 exec()(发送成功)
         *4.如果在 write(QByteArray);后面加一句 socket->waitForBytesWritten();这里就会阻塞等待 直到数据开始发送,这样
         * 不需要exec()在 线程结束之前直接就发送完了
         *socket->waitForConnected()
         * socket->waitForDisconnected()
         * socket->waitForReadyRead()都是一个道理
         */
        qDebug()<<"开始新线程";
       /* QTcpSocket * socket=new QTcpSocket();
        socket->setSocketDescriptor(this->ptr);
    
    
        QByteArray arr;
        QDataStream dts(&arr,QIODevice::WriteOnly);
        dts<<QString("这是数据");
        socket->write(arr);
        */
        mytcpsocket * socket=new mytcpsocket(0,this->ptr);
        socket->waitForBytesWritten();
      // this->exec();
        /*
    1.  连接服务器
    m_tcpSocket->connectToHost("127.0.0.1", 9877);
    connected = m_tcpSocket->waitForConnected();
    只有使用waitForConnected()后,QTcpSocket才真正尝试连接服务器,并返回是否连接的结果。
    
    
    2. 写数据
    m_tcpSocket->write(str.toStdString().c_str(), strlen(str.toStdString().c_str()));
    m_tcpSocket->waitForBytesWritten();
    当使用waitForBytesWritten()后,QTcpSocket才真正发送数据。
    m_tcpSocket->write(str1.toStdString().c_str(), strlen(str1.toStdString().c_str()));
    m_tcpSocket->write(str2.toStdString().c_str(), strlen(str2.toStdString().c_str()));
    的结果是发送了str1str2
    
    
    3. 断开与服务器的连接
    m_tcpSocket->disconnectFromHost()
    m_tcpSocket->waitForDisconnected()
    
    
    4. 善于使用QTcpSocket的SIGNAL:connected(), disconnected(), error(QAbstractSocket::SocketError)
        配合自定义私有开关变量bool connected, QTimer
       可以实现自动重连接等逻辑。
    
    
          */
    }
    
    
    main.cpp
    #include "mainwindow.h"
    #include <QApplication>
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
    
        return a.exec();
    }
    
    
    
    
    
    
    
    
    
    
    
    
    /***********************/
    
    
    
    
    
    
    
    
    
    
    客户端
    useincomming
    useincomming.pro
    #-------------------------------------------------
    #
    # Project created by QtCreator 2016-04-08T09:36:28
    #
    #-------------------------------------------------
    
    
    QT       += core gui
    QT       +=network
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    
    TARGET = useincomming
    TEMPLATE = app
    
    
    
    
    SOURCES += main.cpp
            mainwindow.cpp
    
    
    HEADERS  += mainwindow.h
    
    
    FORMS    += mainwindow.ui
    
    
    mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    
    #include <QMainWindow>
    class QTcpSocket;
    namespace Ui {
    class MainWindow;
    }
    
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    private:
        QTcpSocket * socket;
    private:
        Ui::MainWindow *ui;
    private slots:
        void on_readyread();
        void on_conn();
    };
    
    
    #endif // MAINWINDOW_H
    
    
    mainwindow.cpp
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include<QTcpSocket>
    #include<QHostAddress>
    #include<QString>
    #include<QByteArray>
    #include<QDataStream>
    #include<QMessageBox>
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        this->socket=new QTcpSocket(this);
        this->socket->connectToHost(QHostAddress::LocalHost,520);
        connect(this->socket,SIGNAL(connected()),this,SLOT(on_conn()));
        connect(this->socket,SIGNAL(readyRead()),this,SLOT(on_readyread()));
    }
    
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    void MainWindow::on_readyread()
    {
        QMessageBox::about(this,"提示","开始接受");
        QByteArray array=this->socket->readAll();
        QDataStream dts(&array,QIODevice::ReadOnly);
        QString data;
        dts>>data;
        QMessageBox::about(this,"提示",data);
    
    
    }
    void MainWindow::on_conn()
    {
        QMessageBox::about(this,"提示","连接成功");
    }
    
    
    main.cpp
    #include "mainwindow.h"
    #include <QApplication>
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
    
        return a.exec();
    }
    
  • 相关阅读:
    Python运维开发之路《WEB框架:Django》
    Python运维开发之路《函数进阶》
    Python运维开发之路《编程》
    Python运维开发之路《模块》
    Linux系统运维之Web服务器Nginx安装
    Python运维开发之路《高阶函数》
    Python运维开发之路《函数》
    <读书笔记>软件调试之道 :实证方法
    (知识分享)软硬件调试九法:第九条规则 如果你不修复一个bug,它将永远 存在
    (知识分享)软硬件调试九法:第八条规则 求助他人, 获得全新观点
  • 原文地址:https://www.cnblogs.com/wlzy/p/6801875.html
Copyright © 2020-2023  润新知