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

Wesley13
• 阅读 1029
服务器:
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();
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
C# Aspose.Cells导出xlsx格式Excel,打开文件报“Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃”
报错信息:最近打开下载的Excel,会报如下错误。(xls格式不受影响)!(https://oscimg.oschina.net/oscnet/2b6f0c8d7f97368d095d9f0c96bcb36d410.png)!(https://oscimg.oschina.net/oscnet/fe1a8000d00cec3c
Stella981 Stella981
3年前
Linux查看GPU信息和使用情况
1、Linux查看显卡信息:lspci|grepivga2、使用nvidiaGPU可以:lspci|grepinvidia!(https://oscimg.oschina.net/oscnet/36e7c7382fa9fe49068e7e5f8825bc67a17.png)前边的序号"00:0f.0"是显卡的代
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Github标星5300+,专门为程序员开发文档开源管理系统,我粉了
!(https://oscimg.oschina.net/oscnet/a11909a041dac65b1a36b2ae8b9bcc5c432.jpg)码农那点事儿关注我们,一起学习进步!(https://oscimg.oschina.net/oscnet/f4cce1b7389cb00baaab228e455da78d0
Stella981 Stella981
3年前
Nginx反向代理upstream模块介绍
!(https://oscimg.oschina.net/oscnet/1e67c46e359a4d6c8f36b590a372961f.gif)!(https://oscimg.oschina.net/oscnet/819eda5e7de54c23b54b04cfc00d3206.jpg)1.Nginx反
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这