QTcpServer服务器(incomingConnection方式)

最近没事想着研究一下QT 的服务器,了解了一下QT中相关的接口,突然发现incomingConnection这个方式好简单呀,弄好后测试了一下(没有数据那种,只是简单的收到确认和回复(打开33个client客户端),不保证大批量的数据处理的效率

首先要弄一个数据接收已经处理的socket,只要readyRead和disconnected就行,一个用来接收数据,一个用来销毁连接

// 头文件
#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QTcpSocket>

class TcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TcpSocket(QObject *parent = nullptr);
    
signals:
    void emit_updateClients(QString, int);
    void emit_disConnected(qintptr);
    
//private slots:
//    void onDataRecv();
//    void onDisconnected();
};

#endif // TCPSOCKET_H
// cpp
#include "tcpsocket.h"

TcpSocket::TcpSocket(QObject *parent)
    : QTcpSocket (parent)
{
    connect(this, &QTcpSocket::readyRead, [this](){
        while (this->bytesAvailable() > 0)
        {
            int length = this->bytesAvailable();
            QByteArray data;
            data.resize(length);
            this->read(data.data(), length);                            														// 接受sock数据

            QString strReadData = QString::number(this->socketDescriptor()) + " " + data;
            emit emit_updateClients(strReadData, strReadData.length());

			// for循环是为了模拟,大批量数据处理
            for(int index = 0; index < 1000000; ++index)
            {
            }
            QString strMsg = "Recv Success";
            this->write(strMsg.toStdString().c_str(), strMsg.length());								// 给client客户端返回接收情况
        }
    });
    
    // 调用销毁信号,但是看实际情况,调用这个的时候就销毁了,会导致获取到的描述符为-1, 但是不会影响到其他地方
    connect(this, &QTcpSocket::disconnected, [this](){
        qDebug() << this->socketDescriptor();
        emit emit_disConnected(this->socketDescriptor());               // 获取socket描述符
    });

}

接下来是服务器部分,真的真的超级简单,我都惊了,直接上代码,部分地方会上解释

// 头文件
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QList>
#include <QTcpServer>

#include "TcpServer/tcpsocket.h"

class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    TcpServer(QObject *parent = nullptr, int port = 3366);

    QStringList m_strListData;
signals:
    void emit_UpdateServer(QString, int);
    
protected:
    QList<TcpSocket *> list_tcpclient;						// 用来方便管理各个客户端
    // 用来连接客户端,这个函数需要注意,在QT 5后面的版本参数部分类型要改为 **qintptr** 否则会出现连接上了,但是没有执行函数的情况
    virtual void incomingConnection(qintptr socketDescriptor);		
    
};

#endif // TCPSERVER_H
// cpp
#include "tcpserver.h"
#include <QDebug>

TcpServer::TcpServer(QObject *parent, int port)
    : QTcpServer (parent)
{
    /****************
     * QHostAddress 
     *  Null            空地址
     *  LockHost        IPv4 127.0.0.1 本地回环地址
     *  LockHostIPv6    IPv6           本地回环地址
     *  Broadcast       广播地址 255.255.255.255
     *  Any             IPv4 0.0.0.0   任意地址
     *  AnyIPv6         IPv6           任意地址
    ******************/  
        
    this->listen(QHostAddress::Any, port);
    if(this->isListening())
    {
        qDebug() << "isListening";
    }
}

void TcpServer::incomingConnection(qintptr socketDescriptor)
{
    TcpSocket *socket = new TcpSocket();
    // 设置本 socket 唯一标识符
    socket->setSocketDescriptor(socketDescriptor);

    qDebug() << socketDescriptor << " " << socket->socketDescriptor();
    // 添加到list中方便管理
    list_tcpclient.append(socket);
    
    // 本 socket 接受到的信息
    connect(socket, &TcpSocket::emit_updateClients, [this](QString strInfo, int length){
        // 这个信息要进行什么操作,这里是为了将收到的数据展示
        m_strListData.append(strInfo);
        if(m_strListData.size() >= 200)
        {
            m_strListData.clear();
        }
        Q_UNUSED(length);
    });
    
    // 在list中移除,销毁实际是在 TcpSocket 中触发销毁的时候就已经销毁了
    connect(socket, &TcpSocket::emit_disConnected, [this](int isocketDescriptor){
        for(int index = 0; index < list_tcpclient.size(); ++index)
        {
            QTcpSocket *item = list_tcpclient.at(index);
            
            qDebug() << list_tcpclient.at(index)->socketDescriptor();
            qDebug() << item << " socketDescriptor " << item->socketDescriptor() << " " << isocketDescriptor;
            if(item->socketDescriptor() == isocketDescriptor)
            {
                list_tcpclient.removeAt(index);
                return ;
            }
            qDebug() << "list size " << list_tcpclient.size();
        }
    });
}

UI界面主要就是简单的展示数据,其实上面也看不到,数据有点快

// 主要代码
tcpserver = new TcpServer;

connect(timer, &QTimer::timeout, [this](){
	 ui->textEdit->clear();
	 for(int index = 0; index < tcpserver->m_strListData.size(); ++index)
	 	ui->textEdit->append(tcpserver->m_strListData.at(index));
});
timer->start(100);

下面介绍一下incomingConnection

原文解释:
This virtual function is called by QTcpServer when a new connection is available. The socketDescriptor argument is the native socket descriptor for the accepted connection.
The base implementation creates a QTcpSocket, sets the socket descriptor and then stores the QTcpSocket in an internal list of pending connections. Finally newConnection() is emitted.
Reimplement this function to alter the server’s behavior when a connection is available.
If this server is using QNetworkProxy then the socketDescriptor may not be usable with native socket functions, and should only be used with QTcpSocket::setSocketDescriptor().
Note: If another socket is created in the reimplementation of this method, it needs to be added to the Pending Connections mechanism by calling addPendingConnection().
Note: If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to pass the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() method.

译文:
当有新的连接可用时,QTcpServer将调用这个虚拟函数。socketDescriptor参数是接受连接的本地套接字描述符。
基本实现创建一个QTcpSocket,设置套接字描述符,然后将QTcpSocket存储在一个挂起连接的内部列表中。最后发出newConnection()。
重新实现此函数,以在连接可用时更改服务器的行为。
如果此服务器使用QNetworkProxy,则socketDescriptor可能不能用于本机套接字函数,只能用于QTcpSocket::setSocketDescriptor()。
注意:如果在此方法的重新实现中创建了另一个套接字,则需要通过调用addPendingConnection()将其添加到挂起连接机制。
注意:如果您想要在另一个线程中处理一个新的QTcpSocket对象,那么您必须将socketDescriptor传递给另一个线程,并在那里创建QTcpSocket对象,然后使用它的setSocketDescriptor()方法。

作用说白了,就是,有此函数,然后你有自己的QTcpSocket,那么将这个socket描述符赋值到你的socket中,那么你就可以用这个描述符了

工程代码:
https://download.csdn.net/download/bloke_come/12014976

  • 18
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值