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++内存泄漏及检测工具详解

    最简单的方法当然是借助于专业的检测工具,比较有名如BoundsCheck,功能非常强大,相信做C++开发的人都离不开它。此外就是不使用任何工具,而是自己来实现对内存泄露的监控
    2013-10-10
  • C语言经典顺序表真题演练讲解

    C语言经典顺序表真题演练讲解

    程序中经常需要将一组数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化,顺序表则是将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示
    2022-04-04
  • Opencv实现读取摄像头和视频数据

    Opencv实现读取摄像头和视频数据

    这篇文章主要为大家详细介绍了Opencv实现读取摄像头和视频数据,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • OpenGL画bezier曲线

    OpenGL画bezier曲线

    这篇文章主要为大家详细介绍了OpenGL画bezier曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • Linux网络编程之socket文件传输示例

    Linux网络编程之socket文件传输示例

    这篇文章主要介绍了Linux网络编程之socket文件传输示例,对于基于Linux平台的C程序员来说有一定的借鉴价值,需要的朋友可以参考下
    2014-08-08
  • C语言深入探索数据类型的存储

    C语言深入探索数据类型的存储

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-07-07
  • C语言详细分析讲解多文件的程序设计

    C语言详细分析讲解多文件的程序设计

    所谓的C语言多文件编程就是,将代码实现模块化。比如说一个项目的一项功能放在一个一个文件里,然后将实现这个功能的函数放在一个c文件<BR>
    2022-04-04
  • 详解C++值多态中的传统多态与类型擦除

    详解C++值多态中的传统多态与类型擦除

    值多态是一种介于传统多态与类型擦除之间的多态实现方式,借鉴了值语义,保留了继承,在单继承的适用范围内,程序和程序员都能从中受益。这篇文章主要介绍了C++值多态中的传统多态与类型擦除,需要的朋友可以参考下
    2020-04-04
  • C++ deque容器的用法详解

    C++ deque容器的用法详解

    在处理一些数组的事情,所以随手保留一下Deque容器的使用方法很有必要,接下来通过本文给大家重点介绍C++ deque容器的用法及deque和vector的区别讲解,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • C++Node类Cartographer开始轨迹的处理深度详解

    C++Node类Cartographer开始轨迹的处理深度详解

    这篇文章主要介绍了C++Node类Cartographer开始轨迹的处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-03-03

最新评论