QT编写tcp通信工具(Server端)

 更新时间:2022年08月19日 10:39:13   作者:林子xxx  
这篇文章主要为大家详细介绍了QT编写tcp通信工具,一个类似网上常见的网络调试工具,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了QT编写Server端的tcp通信工具的具体代码,供大家参考,具体内容如下

1.说明

使用qt写一个类似网上常见的网络调试工具。此篇为Server端。Client端在上一篇

2.基本流程

新建QTcpServer对象,为其newConnection信号写槽函数。此为新的Client连接信号,在其对应槽函数里使用nextPendingConnection方法获取Client对象,并为Client添加readyRead(读数据),disconnected(断开连接)两个信号写槽函数。

开始监听使用Server的listen方法,停止监听使用Server的close方法。

主动断开某个连接可使用Client对象的disconnectFromHost方法。需要注意的是,这会触发disconnected信号。应小心处理,避免重复删除链表,导致程序崩溃。

3.代码

这是mainwindow.cpp文件

#include "mainwindow.h"
#include <QApplication>
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->splitter->setStretchFactor(0,2);
    ui->splitter->setStretchFactor(1,1);
    tcpServer = new QTcpServer(this);
    //qWarning()<<QNetworkInterface().allAddresses();
    QString ip=getLocalip();
    if( ip.isEmpty() )
    {
        QMessageBox::about(this,tr("提示"),tr("无本地IP。") ) ;
    }
    else{
 
        ui->ledtIp->setText( ip );   //本地IP
    }
    ui->labHostName->setText(tr("HostName:")+ QHostInfo::localHostName() );
    ui->labHostName->adjustSize();
    ui->ledtPort->setText(tr("8080"));
    ui->btnOpen->setEnabled(true);
    ui->btnSend->setEnabled(false);
    iplistMenu = new  QMenu(  ui->lwdgClientsIp );
    iplistMenu->addAction(ui->actiondel);
    connect( ui->actiondel, SIGNAL(triggered()), this, SLOT(slot_delmenu()));
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slot_newConnectionClient()));
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
//获取本地IP
/*
QString MainWindow::getLocalip()
{
    QHostInfo info = QHostInfo::fromName( QHostInfo::localHostName() );
    foreach(QHostAddress addr,info.addresses())
    {
        if(addr.protocol()==QAbstractSocket::IPv4Protocol)
        {
            return  addr.toString();
        }
    }
    return "";
}
*/
QString MainWindow::getLocalip()
{
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
        if( address.protocol() == QAbstractSocket::IPv4Protocol)
        {
            return address.toString();
        }
    }
        return "";
}
 
//处理来自新的client连接
void MainWindow::slot_newConnectionClient()
{
    while (tcpServer->hasPendingConnections())
    {
        QTcpSocket *client = tcpServer->nextPendingConnection();
        tcpClients.append(client);
 
        ui->lwdgClientsIp->addItem( tr("%1:%2").arg(client->peerAddress().toString()).arg(client->peerPort()) );
        connect(client, SIGNAL(readyRead()), this, SLOT(slot_readData()));
        connect(client, SIGNAL(disconnected()), this, SLOT(slot_disconnectedClient()));
    }
}
 
//接收数据
void MainWindow::slot_readData()
{
    QTcpSocket *obj = (QTcpSocket*)sender();
    QByteArray buf = obj->readAll();
    if(buf.isEmpty())    return;
 
    QString ipc;
    ipc = tr("[%1:%2]>").arg(obj->peerAddress().toString()).arg(obj->peerPort());
    ui->teRecive->appendPlainText(ipc);
    ui->teRecive->appendPlainText(buf);
}
 
//断开连接处理
void  MainWindow::slot_disconnectedClient()
{
    if( !tcpClients.isEmpty() ){
        QTcpSocket *obj = (QTcpSocket*)sender();
        QListWidgetItem *item =  ui->lwdgClientsIp->findItems(
            tr("%1:%2")\
            .arg( obj->peerAddress().toString())\
            .arg( obj->peerPort()),Qt::MatchContains|Qt::MatchEndsWith
            ).at(0);
 
        ui->lwdgClientsIp->removeItemWidget( item );
        delete item;
        obj->close();
        tcpClients.removeOne(obj);
    }
}
 
//打开监听与停止
void MainWindow::on_btnOpen_clicked()
{
    if(ui->btnOpen->text() == "停止")//主动停止监听
    {
 
        if( !tcpClients.isEmpty() )
        for(int i=0; i<tcpClients.length(); i++)//断开所有连接
        {
            tcpClients[i]->disconnectFromHost(); //会触发disconnected信号
        }
        tcpClients.clear();
        tcpServer->close();
        ui->lwdgClientsIp->clear();
        ui->btnOpen->setText("监听");
        ui->btnSend->setEnabled(false);
    }else{ //打开监听
        if(  ui->ledtPort->text().toInt() == 0 )
        {
            QMessageBox::about(this,tr("提示"),tr("请输入端口号。") ) ;
        }
        else
        if( tcpServer->listen( QHostAddress::AnyIPv4  , ui->ledtPort->text().toInt() ) )
        {
            ui->btnOpen->setText("停止");
            ui->btnSend->setEnabled(true);
        }
    }
}
 
//发送数据,UTF8模式
void MainWindow::on_btnSend_clicked()
{
    if( ui->lwdgClientsIp->selectedItems().length() >0 ){
        foreach( QListWidgetItem* item ,ui->lwdgClientsIp->selectedItems() )
        {
            QString clientIP = item->text().split(":")[0];
            int clientPort = item->text().split(":")[1].toInt();
            for(int i=0; i<tcpClients.length(); i++)
            {
                if(tcpClients[i]->peerAddress().toString()==clientIP && tcpClients[i]->peerPort()==clientPort)
                {
                    tcpClients[i]->write(ui->teSend->toPlainText().toUtf8() );
                    break;
                }
            }
        }
    }
}
//“删除”菜单,停止某个Client
void MainWindow:: slot_delmenu()
{
    if(  lwdgitem != NULL )
    {
        if( !tcpClients.isEmpty() ){
            QString clientIP = lwdgitem->text().split(":")[0];
            int clientPort = lwdgitem->text().split(":")[1].toInt();
            for(int i=0; i<tcpClients.length(); i++)
            {
                if(tcpClients[i]->peerAddress().toString()==clientIP && tcpClients[i]->peerPort()==clientPort)
                {
                    tcpClients[i]->disconnectFromHost();
                    break;
                }
            }
        }
    }
}
//弹出菜单
void MainWindow::on_lwdgClientsIp_customContextMenuRequested(const QPoint &pos)
{
    lwdgitem=ui->lwdgClientsIp->itemAt(pos ) ;//判断是否在项目上
    if(  lwdgitem != NULL )
    {
        iplistMenu->exec(QCursor::pos());
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++实现简单推箱子小游戏

    C++实现简单推箱子小游戏

    这篇文章主要为大家详细介绍了C++实现简单推箱子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • C语言深入讲解内存操作问题

    C语言深入讲解内存操作问题

    程序运行的目的是为了得到特定的结果,计算机本质上是用于计算的,既然是用于计算,就需要参与计算的数据,那这些数据就存储在内存中,计算之前参与运算的数据以及运算之后得到的数据,都存储在内存中,所以对内存操作的掌握就尤为重要,下面我们一起来看看
    2022-04-04
  • Opencv基于CamShift算法实现目标跟踪

    Opencv基于CamShift算法实现目标跟踪

    这篇文章主要为大家详细介绍了Opencv基于CamShift算法实现目标跟踪,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++中指针的数据类型和运算相关知识小结

    C++中指针的数据类型和运算相关知识小结

    这篇文章主要介绍了C++中指针的数据类型和运算相关知识小结,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++string容器基本概念详解

    C++string容器基本概念详解

    c++相比c的一个好处就是实现了很多的容器和泛型算法,使得程序员的工作得到了很大的简化,本文重点给大家介绍C++string容器基本概念讲解,需要的朋友参考下吧
    2021-07-07
  • C++中的std::nothrow使用

    C++中的std::nothrow使用

    这篇文章主要介绍了C++中的std::nothrow使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • OpenCV实现图像拼接案例

    OpenCV实现图像拼接案例

    这篇文章主要介绍了OpenCV实现图像拼接案例,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • C++ AnimeGAN实现照片一键动漫化

    C++ AnimeGAN实现照片一键动漫化

    AnimeGAN是是由神经网络风格迁移加生成对抗网络(GAN)而成,它是基于CartoonGAN的改进,并提出了一个更加轻量级的生成器架构。本文将介绍如何运用AnimeGAN实现照片一键动漫化,需要的可以参考一下
    2021-11-11
  • Python扩展C/C++库的方法(C转换为Python)

    Python扩展C/C++库的方法(C转换为Python)

    这篇文章主要介绍了Python扩展C/C++库的方法(C转换为Python),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • C++实现LeetCode(23.合并k个有序链表)

    C++实现LeetCode(23.合并k个有序链表)

    这篇文章主要介绍了C++实现LeetCode(23.合并k个有序链表),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07

最新评论