49.Qt-网络编程之QTCPSocket和QTCPServer(实现简易网络调试助手)
Posted lifexy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了49.Qt-网络编程之QTCPSocket和QTCPServer(实现简易网络调试助手)相关的知识,希望对你有一定的参考价值。
在上章 48.QT-网络通信讲解1,我们学习了网络通信基础后,本章便来实战一篇.源码正在整理中,等下贴地址.
PS:支持客户端和服务器,提供源码,并且服务器支持多客户端连入,并且可以指定与个别客户端发送数据,也可以给所有连入的客户端发送数据.
1.效果图所下所示:
如下图所示,当服务器状态下,如果有客户端连入,会提示客户端信息:
2.效果操作
客户端操作:
服务器操作:
从上面操作可以看出,服务器支持多客户端连入,并且可以指定与个别客户端发送数据,也可以给所有连入的客户端发送数据.
3.首先创建UI
4.注意事项
不管是服务器还是客户端,都可以通过peerAddress()和peerPort()来获取目标地址和目标端口
4.1服务器监听时
比如服务器,则可以通过QTcpSocket的peerAddress()则可以获取连入的客户端地址
也可以通过children()来获取所有连入的客户端(需要注意的是也会获取到服务器本身的tcp地址和端口),示例如下:
QList<QTcpSocket *> m_tcps = m_server.findChildren<QTcpSocket *>(); foreach (QTcpSocket *tcp, m_tcps) qDebug() << "Address:" << tcp->peerAddress (); qDebug() << "Port:" << tcp->peerPort ();
如果我们只向连入的客户端某个端口发送数据时,就可以通过上面的方式筛选出来.
这样做的话如果觉得很麻烦,也可以将之前连接上的客户端存到QList里再进行筛选.
4.2 QTcpSocket步骤
- 首先通过connectToHost()来连接服务器.
- 然后调用waitForConnected()来判断是否连接服务器超时
- 当我们接收到服务器数据的时候,则会发出readyRead()信号,然后再进行read ()读取发来的数据
- 发送数据时,则调用write()函数进行发送,当bytesWritten()信号函数触发时,便可以获取成功发送的数据长度.
注意:如果read到的数据长度量不是自己想要的,此时我们便可以通过bytesAvailable()来读取接收到的数据长度量.当达到多少时,再进行read ()读取.
4.3 QTcpServer步骤
- 首先通过listen(QHostAddress::AnyIPv4, port)来监听所有来自IPV4的客户端
- 当有新的客户端连接服务器的时候,会自动触发newConnection()信号函数,然后我们可以通过通过QTcpSocket * nextPendingConnection()成员函数来获取当前连接上的新的客户端类.然后再对QTcpSocket来进行信号槽绑定
- 当客户端发来数据的时候,则可以通过我们定义的onServerDataReady()来读取数据
- 当我们向某个连接的客户端发送数据时,则通过m_server.findChildren()来筛选出来,然后write即可.
5.代码介绍
5.1 头文件介绍
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpSocket> #include <QTcpServer> #include <QMessageBox> namespace Ui class Widget; class Widget : public QWidget Q_OBJECT QTcpSocket m_client; QTcpServer m_server; QString targetAddr; int targetPort; public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_btn_switch_clicked(); void on_tcpMode_currentIndexChanged(int index); void on_btn_send_clicked(); //发送按钮 void on_betn_clear_clicked(); //清空按钮 //客户端槽函数 void onClientConnected(); void onClientDisconnected(); void onClientDataReady(); void onClientBytesWritten(qint64 bytes); void onClientErr(QAbstractSocket::SocketError socketError); //服务器槽函数 void onServerNewConnection(); void onServerConnected(); void onServerDisconnected(); void onServerDataReady(); void onServerBytesWritten(qint64 bytes); private: void startConnect(bool ison); void initClientSignals(); //初始化客户端信号槽 bool startClient(); //启动客户端 void initServerSignals(); //初始化客户端信号槽 bool startServer(); //启动服务器 Ui::Widget *ui; ; #endif // WIDGET_H
5.2 widget.cpp介绍
该cpp主要是用来处理界面操作的函数
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) ui->setupUi(this); startConnect(false); on_tcpMode_currentIndexChanged(0); initClientSignals(); //初始化客户端信号槽 initServerSignals(); //初始化服务器信号槽 //限制只能数字输入 QRegExp regx("[0-9]+$"); QValidator *validator = new QRegExpValidator(regx, this ); ui->ipAddr1->setValidator( validator ); ui->ipAddr2->setValidator( validator ); ui->ipAddr3->setValidator( validator ); ui->ipAddr4->setValidator( validator ); ui->ipPort->setValidator( validator ); void Widget::on_tcpMode_currentIndexChanged(int index) if(index==0) //clent ui->ipPortLabel->setText("服务器端口号:"); ui->ipAddLabel->show(); ui->ipAdds->show(); ui->targetLabel->hide(); ui->targetObject->hide(); else ui->ipAddLabel->hide(); ui->ipAdds->hide(); ui->ipPortLabel->setText("本地端口号:"); void Widget::on_btn_switch_clicked() //切换连接开关 bool ret; if(ui->btn_switch->text()=="打开连接") if(ui->tcpMode->currentIndex()==0) //启动客户端 ret=startClient() ; else ret=startServer(); if(ret) startConnect(true); else if(ui->tcpMode->currentIndex()==0) //启动客户端 m_client.close(); else if( m_server.isListening() ) QList<QTcpSocket *> m_tcps = m_server.findChildren<QTcpSocket *>(); foreach (QTcpSocket *tcp, m_tcps) tcp->close(); m_server.close(); startConnect(false); void Widget::startConnect(bool ison) if(!ison) ui->btn_switch->setStyleSheet("color:blue;border: 1px solid blue"); ui->btn_switch->setText("打开连接"); //使能 ui->ipAddr1->setEnabled(true); ui->ipAddr2->setEnabled(true); ui->ipAddr3->setEnabled(true); ui->ipAddr4->setEnabled(true); ui->tcpMode->setEnabled(true); ui->ipPort->setEnabled(true); ui->localPort->setText(""); else ui->btn_switch->setStyleSheet("color:red;border: 1px solid red"); ui->btn_switch->setText("关闭连接"); //失能 ui->ipAddr1->setEnabled(false); ui->ipAddr2->setEnabled(false); ui->ipAddr3->setEnabled(false); ui->ipAddr4->setEnabled(false); ui->tcpMode->setEnabled(false); ui->ipPort->setEnabled(false); targetAddr=""; targetPort=0; ui->sendLenLabel->setText("0"); void Widget::on_betn_clear_clicked() ui->recvEdit->clear(); targetAddr=""; targetPort=0; void Widget::on_btn_send_clicked() if(ui->btn_switch->text()!="打开连接") if(ui->tcpMode->currentIndex()==0) //客户端 m_client.write(ui->sendEdit->toPlainText().toLocal8Bit(),ui->sendEdit->toPlainText().toLocal8Bit().length()); else if(ui->targetObject->currentText()!="所有对象") QList<QTcpSocket *> m_tcps = m_server.findChildren<QTcpSocket *>(); foreach (QTcpSocket *tcp, m_tcps) if(ui->targetObject->currentText() == tcp->objectName()) tcp->write(ui->sendEdit->toPlainText().toLocal8Bit(),ui->sendEdit->toPlainText().toLocal8Bit().length()); break; else //所有连接上的客户端都发送一遍 QList<QTcpSocket *> m_tcps = m_server.findChildren<QTcpSocket *>(); foreach (QTcpSocket *tcp, m_tcps) tcp->write(ui->sendEdit->toPlainText().toLocal8Bit(),ui->sendEdit->toPlainText().toLocal8Bit().length()); Widget::~Widget() QList<QTcpSocket *> m_tcps = m_server.findChildren<QTcpSocket *>(); foreach (QTcpSocket *tcp, m_tcps) tcp->close(); if(m_client.isOpen()) m_client.close(); qDebug()<<"m_client close"; delete ui;
5.3 clentHandler.cpp介绍
该cpp主要用来处理客户端操作相关的文件.
#include "widget.h" #include "ui_widget.h" void Widget::initClientSignals() //初始化客户端信号槽 connect(&m_client, SIGNAL(connected()), this, SLOT(onClientConnected())); connect(&m_client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected())); connect(&m_client, SIGNAL(readyRead()), this, SLOT(onClientDataReady())); connect(&m_client, SIGNAL(bytesWritten(qint64)), this, SLOT(onClientBytesWritten(qint64))); connect(&m_client, SIGNAL(error(QAbstractSocket::SocketError )), this, SLOT(onClientErr(QAbstractSocket::SocketError))); bool Widget::startClient() //启动客户端 QString ip = QString("%1.%2.%3.%4").arg(ui->ipAddr1->text()).arg(ui->ipAddr2->text()).arg(ui->ipAddr3->text()).arg(ui->ipAddr4->text()); qDebug()<<ip; m_client.connectToHost(ip, ui->ipPort->text().toInt()); if(m_client.waitForConnected(800)) return true; else QMessageBox::information(this,"提示",QString("连接超时"),QMessageBox::Ok); return false; void Widget::onClientConnected() startConnect(true); QMessageBox::information(this,"提示","连接成功",QMessageBox::Ok); ui->localPort->setText(QString("%1").arg(m_client.localPort())); //显示本地端口号 void Widget::onClientDisconnected() startConnect(false); QMessageBox::information(this,"提示","断开完成",QMessageBox::Ok); void Widget::onClientDataReady() if(m_client.peerAddress().toString()!=targetAddr || m_client.peerPort()!=targetPort ) targetAddr = m_client.peerAddress().toString(); targetPort = m_client.peerPort(); ui->recvEdit->insertPlainText("[接受来自"+ targetAddr+":"+QString("%1").arg(targetPort)+"]:\\r\\n"); ui->recvEdit->moveCursor(QTextCursor::End); ui->recvEdit->insertPlainText(QString::fromLocal8Bit(m_client.readAll())+"\\r\\n"); void Widget::onClientBytesWritten(qint64 bytes) qDebug() << "onBytesWritten:" << bytes; ui->sendLenLabel->setText(QString("%1").arg(ui->sendLenLabel->text().toInt()+bytes)); void Widget::onClientErr(QAbstractSocket::SocketError socketError) qDebug()<<"onClientErr:"<<socketError; m_client.close(); startConnect(false); QMessageBox::information(this,"提示",QString("连接失败:%1").arg((int)socketError),QMessageBox::Ok);
5.4 serverHandler.cpp介绍
该cpp主要用来处理服务器操作相关的文件
#include "widget.h" #include "ui_widget.h" void Widget::initServerSignals() //初始化信号槽 connect(&m_server, SIGNAL(newConnection()), this, SLOT(onServerNewConnection())); bool Widget::startServer() //启动服务器 if(m_server.listen(QHostAddress::AnyIPv4,ui->ipPort->text().toInt())) //只监听IPV4的所有客户端 ui->targetLabel->show(); ui->targetObject->show(); ui->localPort->setText(QString("%1").arg(m_server.serverPort())); return true; else return false; void Widget::onServerNewConnection() qDebug() << "onNewConnection"; QTcpSocket* tcp = m_server.nextPendingConnection(); //获取新的客户端信息 QString info=tcp->peerAddress().toString()+":"+QString("%1").arg(tcp->peerPort()); ui->targetObject->addItem(info); QMessageBox::information(this,"提示",QString("新的客户端连入:%1").arg(info),QMessageBox::Ok); tcp->setObjectName(info); //设置名称,方便查找 connect(tcp, SIGNAL(connected()), this, SLOT(onServerConnected())); connect(tcp, SIGNAL(disconnected()), this, SLOT(onServerDisconnected())); connect(tcp, SIGNAL(readyRead()), this, SLOT(onServerDataReady())); connect(tcp, SIGNAL(bytesWritten(qint64)), this, SLOT(onServerBytesWritten(qint64))); void Widget::onServerConnected() void Widget::onServerDisconnected() QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender()); if( tcp != NULL ) //从连接对象中移除掉 qDebug() << "onServerDisconnected"; qDebug() << "Local Address:" << tcp->peerAddress(); qDebug() << "Local Port:" << tcp->peerPort(); QString info=tcp->peerAddress().toString()+":"+QString("%1").arg(tcp->peerPort()); QMessageBox::information(this,"提示",QString("客户端断开连接:%1").arg(info),QMessageBox::Ok); int index = ui-> targetObject ->findText(info); if(index>=0) ui->targetObject->removeItem(index); void Widget::onServerDataReady() QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender()); if(tcp->peerAddress().toString()!=targetAddr || tcp->peerPort()!=targetPort ) targetAddr = tcp->peerAddress().toString(); targetPort = tcp->peerPort(); ui->recvEdit->insertPlainText("[接受来自"+ targetAddr+":"+QString("%1").arg(targetPort)+"]:\\r\\n"); ui->recvEdit->moveCursor(QTextCursor::End); ui->recvEdit->insertPlainText(QString::fromLocal8Bit(tcp->readAll())+"\\r\\n"); void Widget::onServerBytesWritten(qint64 bytes) qDebug() << "onBytesWritten:" << bytes; ui->sendLenLabel->setText(QString("%1").arg(ui->sendLenLabel->text().toInt()+bytes));
以上是关于49.Qt-网络编程之QTCPSocket和QTCPServer(实现简易网络调试助手)的主要内容,如果未能解决你的问题,请参考以下文章
QT 使用 QTcpSocket来检测 ip 设备的网络状态
Qt creator 找不到,QTcpServer 和 QTcpSocket