Qt多线程TCP服务器

1、功能实现

在这里插入图片描述

2、程序简易流程

用一个Map<String,int> 来存放客户端的 socket的ip和客户端的索引(从0开始)。
围绕着这个创建流程。
1、关键点在于如何处理由服务器发出的 new Socket 连接
2、明白socket 通信的关键信号以及流程
在这里插入图片描述

3、简单剖析部分代码

重要代码1:处理新到来的 socket

void CServerPool::dealNewSocket(qintptr socketDes)
{//处理新到来的 soketDes
    m_numT++;
    if(m_numT<=m_maxT){//处理 没有被超出的
        int index=0;
        if(!m_mapVec.isEmpty()){
            index=m_mapVec.begin().key();
            m_mapVec.remove(index);
        }
        else{
            index=m_numT-1;
        }
		if (!m_threadVec.at(index).m_thread->isRunning()) {
			m_threadVec.at(index).m_thread->start();
			delayMs(600);//延迟600ms 等待线程启动
		}
        emit m_threadVec.at(index).m_myT->newSocket(index,socketDes);//发送到new socket
    }
    else{
        m_numT=m_maxT;//避免前后的index出错

        int index = 0;
        if (!m_mapQue.isEmpty()) {
            index = m_mapQue.begin().key();
            m_mapQue.remove(index);
        }
        else {
            index = m_numQue;
            ++m_numQue;
        }
        if (!m_threadQ->isRunning()){
            m_threadQ->start();
            delayMs(600);//延迟600ms
        }
        emit m_queueT->newSocket(index,socketDes);
    }
}

重要代码2: 线程组 的socket的创建

void MyThread::dealNewSocket(int index,qintptr socketDes)
{
    qDebug()<<"当前线程id"<<QThread::currentThreadId();
    if (!m_socket) {
        m_socket = new MySocket;

        if (!m_socket->t0) {
            m_socket->t0 = new QTimer;
            connect(m_socket->t0, &QTimer::timeout, [=]() {
                double nowTime = QDateTime::currentDateTime().toSecsSinceEpoch();
                if (nowTime - m_socket->m_frontTime > m_socket->m_outTime) {
                    QString str = QString("%1 %2已经超时").arg(
                        m_socket->peerAddress().toString().mid(7)).arg(index);
                    m_socket->t0->stop();
                    if (m_socket->isOpen())
                        m_socket->close();
                    delayMs(1000);
                    emit timeOut(m_socket->index, str);
                }
            });
        }

        //读取
        connect(m_socket, &MySocket::readyRead, [=]() {
            m_socket->t0->stop();
            QByteArray data = m_socket->readAll();
            QString str = m_socket->peerAddress().toString().mid(7);
            QString ip=str+QString(" %1").arg(m_socket->index);
            emit sendData(ip, data);
            m_socket->m_frontTime = QDateTime::currentDateTime().toSecsSinceEpoch();
            m_socket->t0->start(1000);
        });
        //断开连接
        connect(m_socket, &QTcpSocket::disconnected, [=]() {
            QString str = QString("%1 %2已经断开连接呢").arg(
                m_socket->peerAddress().toString().mid(7)).arg(index);
            QString ip = m_socket->peerAddress().toString();
            emit socketDisConnected(m_socket->index, ip, str);
            m_socket->t0->stop();
            if(m_socket->isOpen())
                m_socket->close();
        });
    }
    m_socket->index = index;
    if(m_socket->isOpen())
        m_socket->close();
    m_socket->setSocketDescriptor(socketDes);//设置socket的标志
   
    QString ip=m_socket->peerAddress().toString();
    emit sendAddress(index,ip);
    m_socket->m_frontTime = QDateTime::currentDateTime().toSecsSinceEpoch();
    m_socket->t0->start(1000);//第一次需要自启
}

重要代码3: 队列线程对socket的创建

void QueueThread::dealNewSocket(int index, qintptr socketDes)
{
      MySocket *m_socket = new MySocket;
      m_socket->t0 = new QTimer;
      m_socket->setSocketDescriptor(socketDes);
      m_socket->index = index;
      QString ip=m_socket->peerAddress().toString().mid(7)+QString(" %1").arg(index);

      m_mapDsocket.insert(ip,m_socket);//添加到指定列表中
      //读取
      connect(m_socket->t0, &QTimer::timeout, [=]() {
          double nowTime = QDateTime::currentDateTime().toSecsSinceEpoch();

          if (nowTime - m_socket->m_frontTime > m_socket->m_outTime) {
              int lsIndex = m_socket->index;
              QString str = QString("%1 %2已经超时").arg(
                  m_socket->peerAddress().toString().mid(7)).arg(lsIndex);
              m_socket->t0->stop();
              if (m_socket->isOpen())
                  m_socket->close();
             
              delayMs(1000);
              emit timeOut(str);
          }
      });
      connect(m_socket, &MySocket::readyRead, [=]() {
		  m_socket->t0->stop();
          QByteArray data = m_socket->readAll();
          QString ip = m_socket->peerAddress().toString().mid(7)+
              QString(" %1").arg(m_socket->index);
          emit sendData(ip, data);
          m_socket->m_frontTime = QDateTime::currentDateTime().toSecsSinceEpoch();
          m_socket->t0->start(1000);
      });
      //断开连接
      connect(m_socket, &QTcpSocket::disconnected, [=]() {
          int lsIndex = m_socket->index;
          QString ip = m_socket->peerAddress().toString().mid(7)+QString(" %1").arg(lsIndex);
          QString str = QString("%1已经断开连接呢").arg(ip);
        
          emit socketDisConnected(lsIndex, ip, str);

          m_socket->t0->stop();//关闭定时器
          if (m_socket->isOpen()) {
              m_socket->close();
              delete m_socket;
          }
          m_mapDsocket.remove(ip);
      });
      emit sendAddress(index,ip);//返回成功的地址
      m_socket->t0->start(1000);
      m_socket->m_frontTime = QDateTime::currentDateTime().toSecsSinceEpoch();
}

gitee:https://gitee.com/chenseri/mutiServer
资源地址:https://download.csdn.net/download/a1ngel/82470844

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值