QT网络调试助手
- 1.开发流程
- 2.QTtcp服务器
- 1.1 服务端数据读取
- 1.2 服务端发送数据-所有客户端
- 1.3 服务端自动刷新ip地址
- 1.4 服务端检测客户端断开状态
- 1.5 服务端发送数据-指定特定客户端发送数据
- 1.6 服务端停止监听和断开
- 3.QTtcp客户端
1.开发流程
2.QTtcp服务器
1.添加网络访问权限QT += network2.创建一个新对象server = new QTcpServer(this);3.当监听按钮按下后开始监听
void Widget::on_btnListen_clicked()
{//2.监听:bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 8888-15000//QHostAddress addr("192.168.0.101");port = ui->lineEditPort->text().toUInt();if(!server->listen(QHostAddress(ui->comboBoxAddr->currentText()),port)){ //自动检测ip地址:QHostAddress::AnyQMessageBox msgBox;msgBox.setWindowTitle("监听失败");msgBox.setText("端口号被占用");msgBox.exec();return;}ui->btnListen->setEnabled(false);ui->btnLineOut->setEnabled(true);ui->btnStopListen->setEnabled(true);ui->btnSend->setEnabled(true);//qDebug() << QHostAddress(ui->comboBoxAddr->currentText());
}4.监听到新的newConnection()信号后对新的连接进行处理connect(server,SIGNAL(newConnection()),this,SLOT(on_newClient_connect()));void Widget::on_newClient_connect()
{//所有的数据操作都是TcpSocket进行//bool QTcpServer::hasPendingConnections() const 有新的连接返回Trueif(server->hasPendingConnections()){//QTcpSocket *QTcpServer::nextPendingConnection() 返回下个连接来的connectQTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中qDebug() << "client addr: " <<connection->peerAddress().toString() <<",port: " << connection->peerPort();ui->textEditRev->insertPlainText("客户端地址:" + connection->peerAddress().toString()+"\n客户端端口号:" + QString::number(connection->peerPort())+ "\n");connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));//断开后信号:void QAbstractSocket::disconnected()//connect(connection,SIGNAL(disconnected()),this,SLOT(mdisconnected()));//void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)connect(connection,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(mstateChanged(QAbstractSocket::SocketState)));ui->comboBoxChildren->addItem(QString::number(connection->peerPort()));ui->comboBoxChildren->setCurrentText(QString::number(connection->peerPort()));if(!ui->btnSend->isEnabled()){ui->btnSend->setEnabled(true);}}
}
1.1 服务端数据读取
connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler());void Widget::on_readyRead_handler()
{QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender()); //获得信号的发出者QByteArray RevData = tmpSocket->readAll();ui->textEditRev->insertPlainText("客户端:" + RevData + '\n');ui->textEditRev->moveCursor(QTextCursor::End); //将读取光标移动至尾部ui->textEditRev->ensureCursorVisible(); //确定光标可见
}
1.2 服务端发送数据-所有客户端
在on_newClient_connect()中QTcpSocket *connection = server->nextPendingConnection(); 会将信息也保存在server中,server是全局变量,对server来说,每一个socket都是server的child所以通过其父类QObject的FindChildren可以找到所有的socket
}void Widget::on_btnSend_clicked()
{//QTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();for(QTcpSocket *tmp : tcpSocketClients){//ui->textEditSend->toPlainText().toStdString().c_str()--先将QString转换成标准的c++字符串,再转换成const char*型tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());}
}
1.3 服务端自动刷新ip地址
QNetworkInterfaceQList<QHostAddress> QNetworkInterface::allAddresses()//QList<QHostAddress> QNetworkInterface::allAddresses()QList<QHostAddress> address = QNetworkInterface::allAddresses(); //获取地址for(QHostAddress tmp : address){if(tmp.protocol() == QAbstractSocket::IPv4Protocol) //将ipv4的地址刷入comboxui->comboBoxAddr->addItem(tmp.toString());}
1.4 服务端检测客户端断开状态
注:每次一断开之后必须清空通道即deleteLater();否则server中会一直保留该通道1.信号:void QAbstractSocket::disconnected() connect(connection,SIGNAL(disconnected()),this,SLOT(mdisconnected()));void Widget::mdisconnected()
{QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender()); //获得信号的发出者qDebug() << "client Out";ui->textEditRev->insertPlainText("客户端断开! ");tmpSocket->deleteLater();}2.信号:void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)void Widget::mstateChanged(QAbstractSocket::SocketState socketState)
{QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender()); //获得信号的发出者switch(socketState){case QAbstractSocket::ClosingState://case QAbstractSocket::UnconnectedState:ui->textEditRev->insertPlainText("客户端断开! ");tmpSocket->deleteLater();break;}
}
1.5 服务端发送数据-指定特定客户端发送数据
1.因为ComboBox不提供鼠标点击刷新事件,因此需要重写ComboBox的鼠标点击事件和信号void MyComboBox::mousePressEvent(QMouseEvent *e)
{if(e->button() == Qt::LeftButton){emit ComboBox_clicked();}QComboBox::mousePressEvent(e);
}2.将控件提升为MyComboBox,并绑定信号与槽connect(ui->comboBoxChildren,&MyComboBox::ComboBox_clicked,this,&Widget::MyComboBox_refresh);//刷新ComboBox控件内容---为ComboBox添加接入的端口void Widget::MyComboBox_refresh()
{ui->comboBoxChildren->clear();QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();for(QTcpSocket *tmp : tcpSocketClients){ui->comboBoxChildren->addItem(QString::number(tmp->peerPort()));}ui->comboBoxChildren->addItem("all");
}2.重写发送
void Widget::on_btnSend_clicked()
{//QTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();if(tcpSocketClients.isEmpty()){QMessageBox msg;msg.setText("当前无连接");msg.exec();ui->btnSend->setEnabled(false);return ;}if(ui->comboBoxChildren->currentText() != "all"){QString currentname = ui->comboBoxChildren->currentText();for(QTcpSocket *tmp :tcpSocketClients){if(QString::number(tmp->peerPort()) == currentname){tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());}}}else{for(QTcpSocket *tmp : tcpSocketClients){//ui->textEditSend->toPlainText().toStdString().c_str()--先将QString转换成标准的c++字符串,再转换成const char*型tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());}}
}
1.6 服务端停止监听和断开
void Widget::on_btnStopListen_clicked()
{QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();for(QTcpSocket *tmp : tcpSocketClients){tmp->close();}server->close();ui->btnListen->setEnabled(true);ui->btnLineOut->setEnabled(false);ui->btnStopListen->setEnabled(false);
}void Widget::on_btnLineOut_clicked()
{on_btnStopListen_clicked();delete server;this->close();
}
3.QTtcp客户端
客户端逻辑相对简单直接上代码:
void Widget::on_pushButtonConnect_clicked()
{//void connectToHost(const QHostAddress &address, quint16 port, QIODevice::OpenMode openMode = ReadWrite)client->connectToHost(ui->lineEditIp->text(),ui->lineEditPort->text().toUInt()); //连接服务器timer = new QTimer(this);timer->setSingleShot(1);timer->setInterval(5000);connect(timer,SIGNAL(timeout()),this,SLOT(onTimerOut()));connect(client,SIGNAL(connected()),this,SLOT(onConnected()));//void QAbstractSocket::error(QAbstractSocket::SocketError socketError)connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onError(QAbstractSocket::SocketError)));this->setEnabled(false);timer->start();
}void Widget::mread_data_from_server()
{setInsertColor(Qt::black, "服务器:"+ client->readAll());
}void Widget::on_btnSend_clicked()
{QByteArray sendData = ui->textEditSend->toPlainText().toStdString().c_str();client->write(sendData);setInsertColor(Qt::red,"客户端:" + sendData);
}void Widget::on_pushButtonOut_clicked()
{client->close();ui->textEditRev->append("断开连接\n");ui->pushButtonConnect->setEnabled(true);ui->lineEditIp->setEnabled(true);ui->lineEditPort->setEnabled(true);ui->pushButtonOut->setEnabled(false);ui->btnSend->setEnabled(false);
}void Widget::onConnected()
{timer->stop();this->setEnabled(true);ui->textEditRev->insertPlainText("连接成功\n");ui->pushButtonConnect->setEnabled(false);ui->lineEditIp->setEnabled(false);ui->lineEditPort->setEnabled(false);ui->pushButtonOut->setEnabled(true);ui->btnSend->setEnabled(true);
}void Widget::onError(QAbstractSocket::SocketError error)
{this->setEnabled(true);on_pushButtonOut_clicked();
}void Widget::onTimerOut()
{ui->textEditRev->insertPlainText("连接超时!");client->abort(); //放弃当前连接this->setEnabled(true);}void Widget::setInsertColor(Qt::GlobalColor color, QString str)
{QTextCursor cursor = ui->textEditRev->textCursor();QTextCharFormat format;QBrush brush(color);format.setForeground(brush);cursor.setCharFormat(format);cursor.insertText(str+'\n');ui->textEditRev->moveCursor(QTextCursor::End); //将光标移动至尾部ui->textEditRev->ensureCursorVisible(); //确定光标可见
}
链接:https://pan.baidu.com/s/1uI_bhvufjcuW1R6CrR9P7g
提取码:3urt
–来自百度网盘超级会员V5的分享