qtcpserver用法_qt tcpserver

qtcpserver用法_qt tcpserver【Qt服务器与多线程使用】        ~~~~~~~~        QTcpServer致命缺点就是单线程!!要想实现多线程则需要继承该类之后重写incomingConnection函数,在该函数中将socketDescripto…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

QTcpServer和QTcpSocket使用详解


1、基本使用方法

QTcpServer和QTcpSocket的使用是密不可分的,所以两者一块演示使用方法。

QTcpServer常用信号:

  • newConnection()信号,该信号用于处理新接入的连接

QTcpSocket常用信号:

  • disconnected():断开连接后会触发该信号,一般在该信号的槽函数内处理内存清理释放等工作
  • readyRead():数据到达信号,在该信号的槽函数内处理数据接收

补充:如果想要获取远程接入的IP地址端口等信息,可以使用QTcpSocket的peerAddress()函数获取IP地址,peerPort()获取端口。

基于QTcpServer的TCP服务器多接入echo代码demo:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>

namespace Ui { 
   
class Widget;
}

class Widget : public QWidget
{ 
   
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;

private:
    QTcpServer* tcpServer;

private slots:
    void slotReadyRead();
    void slotNewConnected();
};

#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{ 
   
    ui->setupUi(this);

    tcpServer = new QTcpServer(this);
    QObject::connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewConnected()));
    tcpServer->listen(QHostAddress::Any, 10126);
}

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


void Widget::slotNewConnected()
{ 
   
    while(tcpServer->hasPendingConnections())
    { 
   
        QTcpSocket* socket = tcpServer->nextPendingConnection();
        QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
        QObject::connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
        qDebug("[%s:%d] connected", socket->peerAddress().toString().toStdString().c_str(), socket->peerPort());
    }
}

void Widget::slotReadyRead()
{ 
   
    QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());  // 取得信号发送者对象
    socket->write(socket->readAll());                          // 将数据在发送回去
}

2、基于多线程的使用

         ~~~~~~~~         处理网络的数据一般不会是单线程处理,因为要更新UI界面且还有任务,不可能让tcpSocket死等接收,正常情况下通过QTcpServer获得新接入的客户端QTcpSocket对象来进行收发数据操作,新接入一个连接就创建一个新的线程去处理,但是这里有一个问题就是 QTcpSocket是不支持跨线程调用的,哪怕是以引用或者指针的形式传入到子线程中,也是报错跨线程调用!

         ~~~~~~~~         要想实现多线程则需要继承QTcpServer去重写incomingConnection函数,在该函数中将socketDescriptor参数用信号把他发射出来,或者直接在该函数中创建自己的任务处理线程,在线程中使用QTcpSocket类的setsetSocketDescriptor函数初始化一个socket就可以了。示例代码如下:

#ifndef QMULTITCPSERVER_H
#define QMULTITCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>

class QMultiTcpServer : public QTcpServer
{ 
   
    Q_OBJECT

public:
    QMultiTcpServer(QObject* parent = nullptr);
    virtual ~QMultiTcpServer();

public:
    bool listen(const QHostAddress &address, quint16 port);

protected:
    void incomingConnection(int socketDescriptor);

signals:
    void newConnection(int socketDescriptor);
};

#endif // QMULTITCPSERVER_H

#include "qmultitcpserver.h"

QMultiTcpServer::QMultiTcpServer(QObject* parent):QTcpServer(parent)
{ 
   

}

QMultiTcpServer::~QMultiTcpServer()
{ 
   

}

void QMultiTcpServer::incomingConnection(int socketDescriptor)
{ 
   
    emit this->newConnection(socketDescriptor);
}

bool QMultiTcpServer::listen(const QHostAddress &address, quint16 port)
{ 
   
    return QTcpServer::listen(address, port);
}

示例代码中,我又新增了一个带参数的newConnected信号,目的是为了把socketDescriptor通过信号发射到槽函数中。

然后在主窗体实例化对象:

    tcpServer = new QMultiTcpServer(this);
    QObject::connect(tcpServer, SIGNAL(newConnection(int)), this, SLOT(slotNewConnected(int)));

对应的槽函数如下:

void Widget::slotNewConnected(int socketDescriptor)
{ 
   
    QTcpSocket* socket = new QTcpSocket(this);
    if(!socket->setSocketDescriptor(socketDescriptor))
    { 
   
        delete socket;
        return;
    }

	//
	// 你可以在这里新建一个处理线程,将socketDescriptor传入处理线程,我这里直接是演示怎么使用
	//

    QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
    qDebug("[%s:%d]: connected.", socket->peerAddress().toString().toStdString().c_str(), socket->peerPort());
}

void Widget::slotReadyRead()
{ 
   
    QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());  // 取得当前socket对象
    QByteArray data = socket->readAll();
    qDebug("[%s:%d]:%s", socket->peerAddress().toString().toStdString().c_str(), socket->peerPort(), data.toStdString().c_str());
}

void Widget::slotDisconnected()
{ 
   
    QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());  // 取得当前socket对象
    socket->close();
    qDebug("[%s:%d]: disconnected.", socket->peerAddress().toString().toStdString().c_str(), socket->peerPort());
    delete socket;
}

         ~~~~~~~~         附上多线程tcp服务器的一个demo,代码功能比较简单,就是只有回显功能。客户端接入后新开一个线程处理数据的发送和接收,执行效果如下:
https://github.com/wowyyy/QtThreadServer
在这里插入图片描述


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/197302.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Android UI布局优化之ViewStub[通俗易懂]

    Android UI布局优化之ViewStub[通俗易懂]尊重原创,转载请注明出处:http://blog.csdn.net/a740169405/article/details/50351013前言:在设计模式的单利模式中,懒汉式和饿汉式是其中两种。一种是在类被加载的时候就完成单例对象的初始化,一种是在需要使用该单例的时候才初始化。在android的视图设计中,同样需要使用的这样的设计模式。这样的视图加载起来需要耗费很多的时间。在这几…

  • SQL函数:SUBSTRING截取字符串

    SQL函数:SUBSTRING截取字符串SUBSTRING函数作用截取指定长度的字符SUBSTRING函数用法substring(string,start,length)说明:截取string字符串从start开始length长度的字符SUBSTRING函数使用举例下面举例:截取20181219中的1219字符串–截取目的字符串:1219declare@strvarchar(50)=’2…

  • Idea编译:Java找不到符号「建议收藏」

    Idea编译:Java找不到符号「建议收藏」在使用idea编译运行程序时,有时会出现‘Java找不到符号’的报错,一般可采取以下几种方法:1、选择相应的模块,使用maven的reloadproject2、重启idea3、设置统一的编码,一般为UTF-84、重新build5、经过以上操作依旧没有效,直接追溯报错的位置,发现是log,注释这行代码后重新编译,报错显示下面的log,因此基本判断出是日志这块儿的问题。日志我使用的是@Slf4j注解:lombok依赖使用的1.18.2版本<dependency>

  • vmware16安装centos8_虚拟机centos6安装教程

    vmware16安装centos8_虚拟机centos6安装教程VMware12安装centOS8(vm虚拟机安装centos8教程)前几天Centos8发布了,尽管他是8的第一个版本,有着许多的bug那么今天我们就在VM12上面安装centOS8吧,8这个图形化界面我个人感觉有点丑首先下载iso文件百度下点击进入官网点击马上获得centos然后选择这个选择离你近的镜像地址,点击下载打开vm12点击新建虚拟机点击下一步,如下图这样…

  • 输入成绩,若大于60分,则输出通过_输入一个成绩输出成绩等级

    输入成绩,若大于60分,则输出通过_输入一个成绩输出成绩等级1、给出一个百分制成绩,要求输出成绩等级A,B,C,D,E。90分以上为A,80~89分为B,70~79分为C,60~69分为D,60分以下为E.要求:(1)分别用if语句和switch语句实现;(2)当输入非法数据(如负数)时,应给出“输入数据错误“信息switch语句实现:#includeintmain(){intscor

  • 陶瓷电容分类_陶瓷电容电压级别分类

    陶瓷电容分类_陶瓷电容电压级别分类陶瓷电容分为贴装陶瓷电容和插装陶瓷电容两大类。贴装陶瓷电容是多层陶瓷电容,一般耐压不会超过50V,而层数可以达到4000层,插装的陶瓷电容中包括圆片陶瓷电容和独石电容。圆片陶瓷电容也称瓷片电容,是单层的,耐压从50V~6000V都较为普遍。同样容值下,瓷片电容受温度影响更小,更适合应用在微弱信号放大电路的滤波中。独石电容全称是片式多层陶瓷电容器,(网上有资料说其实就是陶瓷贴片电容的

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号