亲宝软件园·资讯

展开

QT编写tcp通信工具

林子xxx 人气:0

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());
    }
}

加载全部内容

相关教程
猜你喜欢
用户评论