qt tcp服务器1对多

源码下载点这里
已经实现对客户端消息群发以及单独发送,测试是网上下的网络调试助手测试。
因为与单片机进行通信,所以只研究了下tcp的服务器端
在这里插入图片描述
qt的tcp服务器有两个socket一个是监听套接字(QTcpServer),一个是通信套接字(QTcpSocket),创建一个tcpServer对象设置好端口Ip后开始监听
tcpServer->listen(QHostAddress(ip),port)成功监听返回true,当有连接连上tcpServer会触发newConnection信号,newConnection信号对应的槽函数进行通信套接字的连接,以下是监听套接字连接与断开源码

void server::on_pushButton_connect_clicked()
{
    QString temp;
    if(tcpServer->isListening()==true)//服务器正在监听
    {
        if(tcpSocket != nullptr)//判断是否有客户端连接
        {
            for(int i=tcpClientList.length()-1;i>=0;i--)//断开所有连接应从最后开始断开
            {
                //temp =QString("[%1:%2]:退出").arg(tcpClientList.at(i)->peerAddress().toString()).arg(tcpClientList.at(i)->peerPort());
                //ui->textEdit_GetText->append(temp);
                tcpClientList.at(i)->disconnectFromHost();//会触发disconnected信号
                //tcpClientList.removeAt(i);

            }
            if(tcpClientList.isEmpty()==true)
            {
                tcpServer->close();             //关闭服务器
                tcpSocket=nullptr;
                ui->textEdit_GetText->append("停止监听成功");
                ui->pushButton_connect->setText("连接");
                disconnect(tcpServer,&QTcpServer::newConnection,this,&server::NewConnection);
            }
        }
        else
        {
            QString str = "当前没有连接,可重新监听";
            tcpServer->close();
            ui->textEdit_GetText->append(str);
            ui->pushButton_connect->setText("连接");
            disconnect(tcpServer,&QTcpServer::newConnection,this,&server::NewConnection);
        }
    }
    else
    {
        //获取IP和端口

        if(ui->lineEdit_Ip->text() != "")
            ip = ui->lineEdit_Ip->text();
        ui->lineEdit_Ip->setText(ip);
        if(ui->lineEdit_prot->text()=="")
        {
            port=8888;
        }
        else
        {
            port = quint16(ui->lineEdit_prot->text().toUInt());
        }
        ui->lineEdit_prot->setText(QString::number(port));
        //if(true == tcpServer->listen(QHostAddress::Any,port))//监听所有Ip
        if(true == tcpServer->listen(QHostAddress(ip),port))
        {
            ui->textEdit_GetText->append("开始监听");
            ui->pushButton_connect->setText("停止");
            connect(tcpServer,&QTcpServer::newConnection,this,&server::NewConnection);
        }
        else
        {
            ui->textEdit_GetText->append("监听失败");
            return ;
        }
    }
}

处理连接信号

void server::NewConnection()
{
    //取出建立好的套接字
    tcpSocket = tcpServer->nextPendingConnection();
    //获取对方Ip和端口
    QString cip = tcpSocket->peerAddress().toString();
    quint16 prot = tcpSocket->peerPort();
    QString temp= QString("%1.%2:成功连接").arg(cip).arg(prot);
    ui->textEdit_GetText->append(temp);
    //添加到界面以及socket列表中
    temp=temp.split(":")[0];
    ui->comboBox_clinet->addItem(temp);
    tcpClientList.append(tcpSocket);

    connect(tcpSocket,&QTcpSocket::readyRead,this,&server::ReadyRead);
    connect(tcpSocket,&QTcpSocket::disconnected,this,&server::disconnectedSlot);
}

客户端主动断开服务器连接会触发服务器的disconnected信号,同时tcpSocket的disconnectFromHost方法也会触发disconnected信号,断开函数如下

void server::disconnectedSlot()
{
    tcpSocket = (QTcpSocket *)this->sender();//得到发出信号的客户端
    QString temp =QString("%1.%2:退出").arg(tcpSocket->peerAddress().toString()).arg(tcpSocket->peerPort());
    ui->textEdit_GetText->append(temp);
    temp=temp.split(":")[0];
    //从链表中删除
    for(int i=0;i<tcpClientList.length();i++)
    {
        if(tcpClientList.at(i)->peerAddress() == tcpSocket->peerAddress())
        {
            if(tcpClientList.at(i)->peerPort() == tcpSocket->peerPort())
            {
                if(ui->comboBox_clinet->itemText(i) == temp)
                    ui->comboBox_clinet->removeItem(i);
                if(ui->comboBox_clinet->count()==0)
                    ui->comboBox_clinet->setCurrentText("客户端");
                tcpClientList.removeAt(i);
                break;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值