QUdpSocket的writeDatagram,如果写入的地址是一个无效但地址,那么返回值会是什么

在 QUdpSocket 的 writeDatagram 方法中,如果你尝试向一个无效的地址发送数据报,返回值的行为可能会因操作系统和网络栈的具体实现而有所不同。然而,在大多数情况下,当尝试向一个无效或不可达的地址发送数据时,writeDatagram 方法仍然会返回写入的字节数,即数据报的大小,因为从应用程序的角度来看,数据已经被写入到了网络栈。

操作系统和网络栈通常会在后续的处理中发现地址无效,并可能丢弃该数据包,但这不会在 writeDatagram 的返回值中直接反映出来。换句话说,writeDatagram 方法主要关注的是数据是否成功地从应用程序传递到了网络栈,而不是数据是否最终到达了目标地址。

如果你需要确认数据是否成功发送到了目标地址,并且得到了接收者的响应,你需要在应用程序中实现某种形式的确认机制,比如通过接收目标发送回来的应答数据包来确认。

因此,总结来说,如果向一个无效的地址发送数据报,writeDatagram 方法通常会返回写入的字节数,而不会直接返回错误或异常。要检测地址的有效性,你可能需要在更高的层次上实现逻辑,比如通过尝试与目标地址建立其他类型的网络连接(如TCP连接)来验证其可达性,或者通过接收来自目标的响应来确认通信的成功。

 

 

#ifndef MYUDP_H #define MYUDP_H #include <QObject> #include <QUdpSocket> class myudp:public QObject { Q_OBJECT public: explicit myudp(QObject *parent =nullptr); QUdpSocket*getUdpSocket(); bool bindSockInfo(QString ip,quint16 port); signals: void recvMsg(QByteArray); public slots: void readSocket(); void sendMsg(QByteArray msg); private: QUdpSocket *m_sock; QString m_ip; quint16 m_port; QHostAddress dest_ip; quint16 dest_port; }; #endif // MYUDP_H #include "myudp.h" #include <QHostAddress> myudp::myudp(QObject *parent):QObject(parent) { m_sock=new QUdpSocket(this); connect(m_sock,SIGNAL(readyRead()),this,SLOT(readSocket())); } QUdpSocket *myudp::getUdpSocket() { return m_sock; } bool myudp::bindSockInfo(QString ip, quint16 port) { return m_sock->bind(QHostAddress(ip),port); } void myudp::readSocket() { /*QByteArray data; qint64 size=m_sock->pendingDatagramSize(); data.resize(size); m_sock->readDatagram(data.data(),size,&dest_ip,&dest_port); emit recvMsg(data); */ while (m_sock->hasPendingDatagrams()) { QByteArray data; qint64 size = m_sock->pendingDatagramSize(); data.resize(size); QHostAddress sender; quint16 senderPort; m_sock->readDatagram(data.data(), size, &sender, &senderPort); // 更新最后通信方 dest_ip = sender; dest_port = senderPort; emit recvMsg(data); } } void myudp::sendMsg(QByteArray msg) { m_sock->writeDatagram(msg,dest_ip,dest_port); } #ifndef MYTCPSERVER_H #define MYTCPSERVER_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> #include <QList> class mytcpserver:public QObject { Q_OBJECT public: explicit mytcpserver(QObject *parent = nullptr); ~mytcpserver(); bool startServer(QString ip, quint16 port); // 启动服务器 void stopServer(); // 停止服务器 signals: void recvMsg(QByteArray data); // 接收到客户端数据 void clientConnected(QString info); // 客户端连接 void clientDisconnected(QString info); // 客户端断开 public slots: void sendData(QByteArray data); // 发送数据给所有客户端 private slots: void onNewConnection(); // 新客户端接入 void onClientReadyRead(); // 客户端有数据到来 void onClientDisconnected(); // 客户端断开 private: QTcpServer *m_server; QList<QTcpSocket*> m_clients; // 管理多个客户端 QHostAddress getLocalIP(QString ip); // 解析本地地址 }; #endif // MYTCPSERVER_H #include "mytcpserver.h" #include <QHostAddress> #include <QDebug> mytcpserver::mytcpserver(QObject *parent) : QObject(parent), m_server(new QTcpServer(this)) { connect(m_server, &QTcpServer::newConnection, this, &mytcpserver::onNewConnection); } mytcpserver::~mytcpserver() { stopServer(); } QHostAddress mytcpserver::getLocalIP(QString ip) { if (ip == "0.0.0.0" || ip.isEmpty() || ip == "localhost") return QHostAddress::AnyIPv4; return QHostAddress(ip); } bool mytcpserver::startServer(QString ip, quint16 port) { QHostAddress address = getLocalIP(ip); if (m_server->isListening()) { qDebug() << "Server already running."; return true; } bool ok = m_server->listen(address, port); if (ok) { qDebug() << "TCP Server started:" << ip << ":" << port; emit clientConnected("Server started at " + ip + ":" + QString::number(port)); } else { qWarning() << "Listen failed:" << m_server->errorString(); } return ok; } void mytcpserver::stopServer() { for (auto socket : m_clients) { if (socket->state() == QAbstractSocket::ConnectedState) socket->close(); socket->deleteLater(); } m_clients.clear(); if (m_server->isListening()) { m_server->close(); qDebug() << "TCP Server stopped."; } } void mytcpserver::onNewConnection() { while (m_server->hasPendingConnections()) { QTcpSocket *client = m_server->nextPendingConnection(); m_clients.append(client); QString peerInfo = client->peerAddress().toString() + ":" + QString::number(client->peerPort()); qDebug() << "Client connected:" << peerInfo; emit clientConnected("Client connected: " + peerInfo); connect(client, &QTcpSocket::readyRead, this, &mytcpserver::onClientReadyRead); connect(client, &QTcpSocket::disconnected, this, &mytcpserver::onClientDisconnected); } } void mytcpserver::onClientReadyRead() { QTcpSocket *client = qobject_cast<QTcpSocket*>(sender()); if (!client) return; QByteArray data = client->readAll(); emit recvMsg(data); } void mytcpserver::onClientDisconnected() { QTcpSocket *client = qobject_cast<QTcpSocket*>(sender()); if (!client) return; QString peerInfo = client->peerAddress().toString() + ":" + QString::number(client->peerPort()); qDebug() << "Client disconnected:" << peerInfo; emit clientDisconnected("Client disconnected: " + peerInfo); m_clients.removeOne(client); client->deleteLater(); } void mytcpserver::sendData(QByteArray data) { for (int i = 0; i < m_clients.size(); ++i) { QTcpSocket *client = m_clients[i]; if (client && client->state() == QAbstractSocket::ConnectedState) { client->write(data); } else { // 清理无效连接 m_clients.removeAt(i); --i; client->deleteLater(); } } } #ifndef MYTCPCLIENT_H #define MYTCPCLIENT_H #include <QObject> #include <QTcpSocket> class mytcpclient:public QObject { Q_OBJECT public: explicit mytcpclient(QObject *parent=nullptr); ~mytcpclient(); bool connectToHost(QString ip, quint16 port); void disconnectFromHost(); void sendData(QByteArray data); signals: void recvMsg(QByteArray data); void connectedStatus(bool connected, QString reason); private slots: void onConnected(); void onDisconnected(); void onReadyRead(); private: QTcpSocket *m_socket; }; #endif // MYTCPCLIENT_H #include "mytcpclient.h" #include <QTcpSocket> #include <QDebug> mytcpclient::mytcpclient(QObject *parent) : QObject(parent), m_socket(new QTcpSocket(this)) { connect(m_socket, &QTcpSocket::connected, this, &mytcpclient::onConnected); connect(m_socket, &QTcpSocket::disconnected, this, &mytcpclient::onDisconnected); connect(m_socket, &QTcpSocket::readyRead, this, &mytcpclient::onReadyRead); } mytcpclient::~mytcpclient() { disconnectFromHost(); } bool mytcpclient::connectToHost(QString ip, quint16 port) { if (m_socket->state() == QAbstractSocket::ConnectedState || m_socket->state() == QAbstractSocket::ConnectingState) { return true; // 避免重复连接 } m_socket->connectToHost(ip, port); } void mytcpclient::disconnectFromHost() { m_socket->disconnectFromHost(); } void mytcpclient::sendData(QByteArray data) { if (m_socket->state() == QAbstractSocket::ConnectedState) { m_socket->write(data); } else { qWarning() << "Not connected, cannot send data."; emit connectedStatus(false, "Not connected"); } } void mytcpclient::onConnected() { qDebug() << "Connected to server"; emit connectedStatus(true, "Connected"); } void mytcpclient::onDisconnected() { qDebug() << "Disconnected from server"; emit connectedStatus(false, "Disconnected"); } void mytcpclient::onReadyRead() { QByteArray data = m_socket->readAll(); emit recvMsg(data); } #ifndef MAINWINDOW_H #define MAINWINDOW_H #include "myudp.h" #include "mytcpclient.h" #include "mytcpserver.h" #include <QString> #include <QByteArray> #include <QVariant> #include <QDebug> #include <QStringList> #include <QMap> #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void createUdp(); void createTcpServer(); void createTcpClient(); void closeCurrentConnection(); enum CommMode { MODE_UDP, MODE_TCP_SERVER, MODE_TCP_CLIENT }; signals: void sendMsg(QByteArray); private slots: void on_sendpushButton_clicked(); void comboxChanged(int index); void recvMsg(QByteArray); //接收区设置 void on_pushButton_8_clicked();//network send void on_savefile_checkBox_stateChanged(int arg1); void on_auto_checkBox_stateChanged(int arg1); void on_hex_checkBox_stateChanged(int arg1); void on_pause_checkBox_stateChanged(int arg1); void on_savedata_pushButton_clicked(); void on_clear_pushButton_clicked(); private: Ui::MainWindow *ui; //network myudp *m_udp=nullptr; mytcpserver *m_tcpServer = nullptr; mytcpclient *m_tcpClient = nullptr; CommMode currentMode = MODE_UDP; //接收区设置 bool m_hexDisplay=false; bool m_pauseDisplay=false; QFile m_logFile; QStringList m_pendingMessages; QString formatHex(const QByteArray &data); }; #endif // MAINWINDOW_H #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <QFileDialog> #include <QTextStream> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //ui->comboBox_6->addItem("UDP"); //ui->comboBox_6->addItem("TCP Sever"); //ui->comboBox_6->addItem("TCP Client"); ui->pushButton_8->setText("链接"); ui->pushButton_8->setAccessibleName("OFF"); connect(ui->comboBox_6,SIGNAL(currentIndexChanged(int)), this,SLOT(comboxChanged(int))); createUdp(); createTcpServer(); createTcpClient(); ui->recvtextEdit->setLineWrapMode(QTextEdit::WidgetWidth); connect(ui->savefile_checkBox, &QCheckBox::stateChanged, this, &MainWindow::on_savefile_checkBox_stateChanged); connect(ui->auto_checkBox, &QCheckBox::stateChanged, this, &MainWindow::on_auto_checkBox_stateChanged); connect(ui->hex_checkBox, &QCheckBox::stateChanged, this, &MainWindow::on_hex_checkBox_stateChanged); connect(ui->pause_checkBox, &QCheckBox::stateChanged, this, &MainWindow::on_pause_checkBox_stateChanged); connect(ui->savedata_pushButton, &QPushButton::clicked, this, &MainWindow::on_savedata_pushButton_clicked); connect(ui->clear_pushButton, &QPushButton::clicked, this, &MainWindow::on_clear_pushButton_clicked); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_sendpushButton_clicked() { QString data=ui->sendtextEdit->toPlainText(); emit sendMsg(data.toLocal8Bit()); } void MainWindow::createUdp() { if (m_udp) delete m_udp; m_udp=new myudp(this); connect(this,SIGNAL(sendMsg(QByteArray)),m_udp,SLOT(sendMsg(QByteArray))); connect(m_udp,SIGNAL(recvMsg(QByteArray)),this,SLOT(recvMsg(QByteArray))); currentMode = MODE_UDP; } void MainWindow::createTcpServer() { if (m_tcpServer) delete m_tcpServer; m_tcpServer = new mytcpserver(this); connect(this, &MainWindow::sendMsg, m_tcpServer, &mytcpserver::sendData); connect(m_tcpServer, &mytcpserver::recvMsg, this, &MainWindow::recvMsg); connect(m_tcpServer, &mytcpserver::clientConnected, [&](const QString& info){ ui->recvtextEdit->append("[SERVER] " + info); }); connect(m_tcpServer, &mytcpserver::clientDisconnected, [&](const QString& info){ ui->recvtextEdit->append("[SERVER] " + info); }); currentMode = MODE_TCP_SERVER; } void MainWindow::createTcpClient() { if (m_tcpClient) delete m_tcpClient; m_tcpClient = new mytcpclient(this); connect(this, &MainWindow::sendMsg, m_tcpClient, &mytcpclient::sendData); connect(m_tcpClient, &mytcpclient::recvMsg, this, &MainWindow::recvMsg); connect(m_tcpClient, &mytcpclient::connectedStatus, [&](bool connected, const QString& reason){ QString status = connected ? "Connected" : "Disconnected"; ui->recvtextEdit->append(QString("[CLIENT] %1: %2").arg(status, reason)); }); currentMode = MODE_TCP_CLIENT; } void MainWindow::closeCurrentConnection() { switch(currentMode) { case MODE_UDP: if (m_udp) { m_udp->getUdpSocket()->close(); } break; case MODE_TCP_SERVER: if (m_tcpServer) { m_tcpServer->stopServer(); } break; case MODE_TCP_CLIENT: if (m_tcpClient) { m_tcpClient->disconnectFromHost(); } break; } } void MainWindow::comboxChanged(int index) { closeCurrentConnection(); if(0==index){ createUdp(); }else if(1==index){ createTcpServer(); }else { createTcpClient(); } /* // 关闭当前连接 switch(index) { case 0: createUdp(); break; case 1: createTcpServer(); break; case 2: createTcpClient(); break; } */ } void MainWindow::recvMsg(QByteArray msg) { // ui->recvtextEdit->append(QString::fromLocal8Bit(msg)); // 写入文件(如果开启) if (m_logFile.isOpen()) { QTextStream out(&m_logFile); out << (m_hexDisplay ? formatHex(msg) : QString::fromLocal8Bit(msg)) << "\n"; m_logFile.flush(); } // 暂停显示则缓存 if (m_pauseDisplay) { m_pendingMessages.append(m_hexDisplay ? formatHex(msg) : QString::fromLocal8Bit(msg)); return; } // 正常显示 ui->recvtextEdit->append(m_hexDisplay ? formatHex(msg) : QString::fromLocal8Bit(msg)); } void MainWindow::on_pushButton_8_clicked() { /* QString ip=ui->lineEdit_4->text(); quint16 port=ui->lineEdit_5->text().toShort(); if(ui->pushButton_8->accessibleName()=="OFF"){ m_udp->bindSockInfo(ip,port); ui->pushButton_8->setText("断开"); ui->pushButton_8->setAccessibleName("ON"); }else if(ui->pushButton_8->accessibleName()=="ON"){ QUdpSocket*socket=m_udp->getUdpSocket(); socket->close(); ui->pushButton_8->setText("链接"); ui->pushButton_8->setAccessibleName("OFF"); } */ QString ip = ui->iplineEdit->text().trimmed(); bool ok; quint16 port = ui->portlineEdit->text().toUShort(&ok); if (ip.isEmpty()) { QMessageBox::warning(this, "错误", "请输入 IP 地址!"); return; } if (!ok || port == 0) { QMessageBox::warning(this, "错误", "请输入有效端口号(1-65535)!"); return; } QPushButton *btn = ui->pushButton_8; QString state = btn->accessibleName(); if (state == "OFF") { bool success = false; switch(currentMode) { case MODE_UDP: success = m_udp->bindSockInfo(ip, port); break; case MODE_TCP_SERVER: success = m_tcpServer->startServer(ip, port); break; case MODE_TCP_CLIENT: success = m_tcpClient->connectToHost(ip, port); break; } if (success) { btn->setText("断开"); btn->setAccessibleName("ON"); } else { QMessageBox::critical(this, "失败", "连接/启动失败,请检查设置。"); } } else { closeCurrentConnection(); btn->setText("链接"); btn->setAccessibleName("OFF"); } } //接收器设置 void MainWindow::on_savefile_checkBox_stateChanged(int arg1) { QString content = ui->recvtextEdit->toPlainText(); if (content.isEmpty()) return; QString file = QFileDialog::getSaveFileName(this, "接收区显示内容另存为", "", "Text Files (*.txt)"); if (!file.isEmpty()) { QFile f(file); if (f.open(QIODevice::WriteOnly | QIODevice::Text)) f.write(content.toUtf8()); } } void MainWindow::on_auto_checkBox_stateChanged(int arg1) { ui->recvtextEdit->setLineWrapMode(arg1 ? QTextEdit::WidgetWidth : QTextEdit::NoWrap); } void MainWindow::on_hex_checkBox_stateChanged(int arg1) { m_hexDisplay=arg1;; ui->recvtextEdit->clear(); } void MainWindow::on_pause_checkBox_stateChanged(int arg1) { m_pauseDisplay=arg1; if(!arg1&&m_pendingMessages.isEmpty()){ for(const QString &msg:m_pendingMessages) ui->recvtextEdit->append(msg); m_pendingMessages.clear(); } } void MainWindow::on_savedata_pushButton_clicked() { QString content = ui->recvtextEdit->toPlainText(); if (content.isEmpty()) return; QString file = QFileDialog::getSaveFileName(this, "保存数据", "", "Text Files (*.txt)"); if (!file.isEmpty()) { QFile f(file); if (f.open(QIODevice::WriteOnly | QIODevice::Text)) f.write(content.toUtf8()); } } void MainWindow::on_clear_pushButton_clicked() { ui->recvtextEdit->clear(); } QString MainWindow::formatHex(const QByteArray &data) { QString result; for (uchar b : data) result += QString("%1 ").arg(b, 2, 16, QLatin1Char('0')).toUpper(); return result.trimmed(); } 保留核心实现,去除冗余,检查代码中是否有需要修改的错误
最新发布
12-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值