环境
Windows:Qt5.15.2(VS2022)
Linux:Qt5.12.12(gcc)
源代码
TCP服务器
头文件:
#ifndef TCPSERVERWIDGET_H
#define TCPSERVERWIDGET_H
#include <QWidget>
namespace Ui {
class TCPServerWidget;
}
class QTcpServer;
class QTcpSocket;
class TCPServerWidget : public QWidget {
Q_OBJECT
public:
explicit TCPServerWidget(QWidget *parent = nullptr);
~TCPServerWidget();
private:
QTcpSocket *socket(int row);
private slots:
void on_listen_clicked();
void on_close_clicked();
void on_send_clicked();
void on_clear_clicked();
private:
Ui::TCPServerWidget *ui;
QTcpServer *m_Server;
QList<QTcpSocket *> m_Clients;
};
#endif // TCPSERVERWIDGET_H
源文件:
#include "tcpserverwidget.h"
#include "common.h"
#include "ui_tcpserverwidget.h"
#include <QHeaderView>
#include <QTcpServer>
#include <QTcpSocket>
TCPServerWidget::TCPServerWidget(QWidget *parent)
: QWidget(parent), ui(new Ui::TCPServerWidget) {
ui->setupUi(this);
ui->localIp->addItem("Any");
ui->localIp->addItems(getIPAddresses());
ui->clientTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->clientTable->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->clientTable->horizontalHeader()->setSectionResizeMode(
QHeaderView::Stretch);
m_Server = new QTcpServer;
connect(m_Server, &QTcpServer::newConnection, [=]() {
QTcpSocket *tcpSocket = m_Server->nextPendingConnection();
QString ip = tcpSocket->peerAddress().toString();
quint16 port = tcpSocket->peerPort();
appendLog(ui->textEdit, QString("%1:%2:connect").arg(ip).arg(port));
bool r = false;
for (int i = 0; i < ui->clientTable->rowCount(); ++i) {
QTableWidgetItem *ipitem = ui->clientTable->item(i, 0);
QTableWidgetItem *portitem = ui->clientTable->item(i, 1);
if (nullptr != ipitem && nullptr != portitem &&
ipitem->text() == ip && portitem->text().toUShort() == port) {
r = true;
break;
}
}
connect(tcpSocket, &QTcpSocket::disconnected, [=]() {
appendLog(ui->textEdit,
QString("%1:%2 disconnected")
.arg(tcpSocket->peerAddress().toString())
.arg(tcpSocket->peerPort()));
for (int i = 0; i < ui->clientTable->rowCount(); ++i) {
QTableWidgetItem *ipitem = ui->clientTable->item(i, 0);
QTableWidgetItem *portitem = ui->clientTable->item(i, 1);
if (nullptr != ipitem && nullptr != portitem &&
ipitem->text() == ip &&
portitem->text().toUShort() == port) {
ui->clientTable->removeRow(i);
break;
}
}
for (QTcpSocket *socket : m_Clients) {
if (ip == socket->peerAddress().toString() &&
port == socket->peerPort()) {
m_Clients.removeOne(socket);
socket = nullptr;
break;
}
}
});
connect(tcpSocket, &QTcpSocket::readyRead, [=]() {
QByteArray data = (ui->toHex->isChecked())
? tcpSocket->readAll().toHex()
: tcpSocket->readAll();
appendLog(ui->textEdit,
QString("%1:%2:%3").arg(ip).arg(port).arg(QString(data)));
});
m_Clients.append(tcpSocket);
int row = ui->clientTable->rowCount();
ui->clientTable->insertRow(row);
ui->clientTable->setItem(row, 0, new QTableWidgetItem(ip));
ui->clientTable->setItem(row, 1,
new QTableWidgetItem(QString::number(port)));
});
}
TCPServerWidget::~TCPServerWidget() {
delete ui;
}
QTcpSocket *TCPServerWidget::socket(int row) {
QTableWidgetItem *ipitem = ui->clientTable->item(row, 0);
QTableWidgetItem *portitem = ui->clientTable->item(row, 1);
if (nullptr != ipitem && nullptr != portitem) {
QString ip = ipitem->text();
quint16 port = portitem->text().toUShort();
for (QTcpSocket *tcpSocket : m_Clients) {
if (ip == tcpSocket->peerAddress().toString() &&
port == tcpSocket->peerPort())
return tcpSocket;
}
}
return nullptr;
}
void TCPServerWidget::on_listen_clicked() {
if (ui->listen->text() == "listen") {
if (m_Server->listen((ui->localIp->currentText() == "Any")
? QHostAddress::Any
: QHostAddress(ui->localIp->currentText()),
ui->localPort->value())) {
ui->listen->setText("listening");
appendLog(ui->textEdit, "start listening");
} else {
appendLog(ui->textEdit,
"start listen error:" + m_Server->errorString());
}
} else {
m_Server->close();
ui->listen->setText("listen");
for (QTcpSocket *tcpSocket : m_Clients) {
tcpSocket->close();
tcpSocket->disconnectFromHost();
}
m_Clients.clear();
appendLog(ui->textEdit, "stop listening");
}
}
void TCPServerWidget::on_close_clicked() {
int row = ui->clientTable->currentRow();
QTcpSocket *tcpSocket = socket(row);
if (nullptr != tcpSocket) {
tcpSocket->close();
tcpSocket->disconnectFromHost();
}
}
void TCPServerWidget::on_send_clicked() {
QByteArray data = (ui->toHex->isChecked())
? QByteArray::fromHex(ui->message->text().toUtf8())
: ui->message->text().toUtf8();
int row = ui->clientTable->currentRow();
QTcpSocket *tcpSocket = socket(row);
if (nullptr != tcpSocket)tcpSocket->write(data, data.size());
}
void TCPServerWidget::on_clear_clicked() {
ui->textEdit->clear();
}
TCP客户端
头文件:
#ifndef TCPCLIENTWIDGET_H
#define TCPCLIENTWIDGET_H
#include <QWidget>
namespace Ui {
class TCPClientWidget;
}
class QTcpSocket;
class TCPClientWidget : public QWidget {
Q_OBJECT
public:
explicit TCPClientWidget(QWidget *parent = nullptr);
~TCPClientWidget();
private slots:
void on_connect_clicked();
void on_send_clicked();
void on_clear_clicked();
private:
Ui::TCPClientWidget *ui;
QTcpSocket *m_Socket;
};
#endif // TCPCLIENTWIDGET_H
源文件:
#include "tcpclientwidget.h"
#include "common.h"
#include "ui_tcpclientwidget.h"
#include <QFutureWatcher>
#include <QTcpSocket>
#include <QtConcurrent/QtConcurrent>
TCPClientWidget::TCPClientWidget(QWidget *parent)
: QWidget(parent), ui(new Ui::TCPClientWidget) {
ui->setupUi(this);
ui->localIp->addItems(getIPAddresses());
m_Socket = new QTcpSocket;
connect(m_Socket, &QTcpSocket::disconnected, [=]() {
ui->connect->setText("connect");
appendLog(ui->textEdit, "disconnect");
});
connect(m_Socket, &QTcpSocket::readyRead, [=]() {
QByteArray data = (ui->toHex->isChecked()) ? m_Socket->readAll().toHex()
: m_Socket->readAll();
appendLog(ui->textEdit, QString(data));
});
}
TCPClientWidget::~TCPClientWidget() {
delete ui;
}
void TCPClientWidget::on_connect_clicked() {
if ("connect" == ui->connect->text()) {
if (ui->bind->isChecked()) {
if (!m_Socket->bind(QHostAddress(ui->localIp->currentText()),
ui->localPort->value())) {
appendLog(ui->textEdit,
"bind error:" + m_Socket->errorString());
return;
}
}
ui->connect->setEnabled(false);
m_Socket->connectToHost(QHostAddress(ui->serverIp->text()),
ui->serverPort->value());
if (m_Socket->waitForConnected()) {
ui->connect->setText("disconnect");
appendLog(ui->textEdit, "connect");
} else
appendLog(ui->textEdit, "connect error:" + m_Socket->errorString());
ui->connect->setEnabled(true);
} else {
m_Socket->close();
m_Socket->disconnectFromHost();
ui->connect->setText("connect");
appendLog(ui->textEdit, "disconnect");
}
}
void TCPClientWidget::on_send_clicked() {
QByteArray data = (ui->toHex->isChecked())
? QByteArray::fromHex(ui->message->text().toUtf8())
: ui->message->text().toUtf8();
if (m_Socket->isOpen()) m_Socket->write(data, data.size());
}
void TCPClientWidget::on_clear_clicked() {
ui->textEdit->clear();
}
UDP
头文件:
#ifndef UDPWIDGET_H
#define UDPWIDGET_H
#include <QWidget>
namespace Ui {
class UDPWidget;
}
class QUdpSocket;
class UDPWidget : public QWidget {
Q_OBJECT
public:
explicit UDPWidget(QWidget *parent = nullptr);
~UDPWidget();
private slots:
void on_bind_clicked();
void on_send_2_clicked();
void on_clear_2_clicked();
private:
Ui::UDPWidget *ui;
QUdpSocket *m_Socket;
};
#endif // UDPWIDGET_H
源文件:
#include "udpwidget.h"
#include <QUdpSocket>
#include "common.h"
#include "ui_udpwidget.h"
UDPWidget::UDPWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UDPWidget) {
ui->setupUi(this);
ui->localIp_2->addItems(getIPAddresses());
m_Socket = new QUdpSocket;
connect(m_Socket, &QUdpSocket::readyRead, [=]() {
while (m_Socket->hasPendingDatagrams()) {
QByteArray data;
QHostAddress host;
quint16 port;
data.resize(m_Socket->pendingDatagramSize());
m_Socket->readDatagram(data.data(), data.size(), &host, &port);
data = (ui->toHex_2->isChecked()) ? data.toHex() : data;
appendLog(ui->textEdit, QString("%1:%2:%3")
.arg(host.toString())
.arg(port)
.arg(QString(data)));
}
});
}
UDPWidget::~UDPWidget() { delete ui; }
void UDPWidget::on_bind_clicked() {
if (ui->bind->text() == "bind") {
if (m_Socket->bind(QHostAddress(ui->localIp_2->currentText()),
ui->localPort_2->value()))
ui->bind->setText("unbind");
else
appendLog(ui->textEdit, "bind error:" + m_Socket->errorString());
} else {
m_Socket->abort();
ui->bind->setText("bind");
}
}
void UDPWidget::on_send_2_clicked() {
QByteArray data = (ui->toHex_2->isChecked())
? QByteArray::fromHex(ui->message_2->text().toUtf8())
: ui->message_2->text().toUtf8();
m_Socket->writeDatagram(data, QHostAddress(ui->serverIp->text()),
ui->serverPort->value());
}
void UDPWidget::on_clear_2_clicked() { ui->textEdit->clear(); }
运行效果
TCP服务器与多个客户端通信:
UDP之间通信: