0
点赞
收藏
分享

微信扫一扫

Linux系统运维脚本:shell脚本查看一定网段范围在线网络设备的ip地址和不在线的网络设备的数量(查看在线和不在线网络设备)

洲行 2024-03-01 阅读 8

TCP

TCP(Transmission Control Protocol,传输控制协议)是一个用于数据传输的低层的网络协议,多个互联网协议(包括 HTTP 和 FTP)都是基于 TCP 协议的。它是可靠的、面向流、面向连接的传输协议,特别适合连续数据的传输。

TCP 通信必须先建立连接,分为客户端和服务端,也就是所谓的 C/S(Client/Server)模型,如图:

在这里插入图片描述

客户端

客户端使用 QTcpSocket 与 TCP 服务器建立连接并通信。

QTcpSocket 类除了构造函数和析构函数,其他函数都是从 QAbstractSocket 继承或重定义的。QAbstractSocket 用于 TCP 通信的主要接口函数如图:

在这里插入图片描述

客户端的 QTcpSocket 实例首先通过 connectToHost() 尝试连接到服务器,需要指定服务器的 IP 地址和端口号。connectToHost() 是异步方式连接服务器,不会阻塞程序运行,连接后发射 connected() 信号。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void onConnected();
void onDisconnected();
void onReadyRead();

void on_btnConnect_clicked();
void on_btnSendMsg_clicked();

private:
Ui::Widget *ui;

QTcpSocket *m_client{};
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "./ui_widget.h"

#include <QHostAddress>

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

setWindowTitle("客户端");

m_client = new QTcpSocket(this);
connect(m_client, &QTcpSocket::connected, this, &Widget::onConnected);
connect(m_client, &QTcpSocket::disconnected, this, &Widget::onDisconnected);
connect(m_client, &QTcpSocket::readyRead, this, &Widget::onReadyRead);
}

Widget::~Widget()
{
m_client->abort();
delete ui;
}

void Widget::onConnected()
{
ui->labConnectState->setText("Connecting");
}

void Widget::onDisconnected()
{
ui->labConnectState->setText("Disconnect");
}

void Widget::onReadyRead()
{
ui->textEditRecv->setText(m_client->readAll());
}

void Widget::on_btnConnect_clicked()
{
QString str = ui->btnConnect->text();
if (str == "Connect") {
ui->btnConnect->setText("Disconnect");

if (m_client->state() == QAbstractSocket::SocketState::ConnectingState) {
m_client->close();
}

QString address = ui->leAddress->text();
QString port = ui->lePort->text();
m_client->connectToHost(QHostAddress(address), port.toInt());
} else {
ui->btnConnect->setText("Connect");
m_client->close();
}
}

void Widget::on_btnSendMsg_clicked()
{
QString msg = ui->textEditSend->toPlainText();
m_client->write(msg.toLocal8Bit());
}

界面如图:

在这里插入图片描述

服务端

服务端程序必须使用 QTcpServer 进行端口监听,建立服务器。QTcpSocket 用于建立连接后使用套接字。

QTcpServer 是从 QObject 继承的类,它主要用于服务器建立网络监听,创建网络 Socket 连接。QTcpServer 类的主要接口函数如下所示:

在这里插入图片描述

服务端可以使用 QTcpServer::listen() 指定监听的 IP 地址和端口,一般一个服务程序只监听某个端口的网络连接。

当有新的客户端接入时,QTcpServer 内部的 incomingConnection() 函数会创建一个与客户端连接的 QTcpSocket 对象,然后发出信号 newConnection()。可以使用 nextPendingConnection() 接受客户端的连接,然后使用 QTcpSocket 与客户端通信。所以在客户端与服务端建立连接后,具体的数据通信是通过 QTcpSocket 完成的。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void onNewConnection();
void onReadyRead();
void onClientDisconnected();

void on_btnClose_clicked();
void on_btnSendMsg_clicked();

private:
Ui::Widget *ui;

QTcpServer *m_server{};
QTcpSocket *m_socket{};
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "./ui_widget.h"

#include <QHostAddress>
#include <QHostInfo>

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

setWindowTitle("服务端");

// 获取本地 ip
QString ip;
QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());
for (auto &address : info.addresses()) {
if (address != QHostAddress::LocalHost && address.toIPv4Address()) {
ip = address.toString();
break;
}
}
ui->leAddress->setText(ip);
ui->lePort->setText("1234");

m_server = new QTcpServer(this);
m_server->listen(QHostAddress::Any, 1234);
connect(m_server, &QTcpServer::newConnection, this, &Widget::onNewConnection);
}

Widget::~Widget()
{
delete ui;
}

void Widget::onNewConnection()
{
m_socket = m_server->nextPendingConnection();
// 告知客户端连接成功
m_socket->write("Congratulations on successfully connecting !");
connect(m_socket, &QTcpSocket::readyRead, this, &Widget::onReadyRead);
connect(m_socket, &QTcpSocket::disconnected, this, &Widget::onClientDisconnected);

// 更新连接状态显示
ui->labConnectState->setText(QString("new connection %1 %2")
.arg(m_socket->peerAddress().toString())
.arg(m_socket->peerPort()));
}

void Widget::onReadyRead()
{
ui->textEditRecv->setText(m_socket->readAll());
}

void Widget::onClientDisconnected()
{
ui->labConnectState->setText(QString("%1 %2 disconnected")
.arg(m_socket->peerAddress().toString())
.arg(m_socket->peerPort()));
}

void Widget::on_btnClose_clicked()
{
m_server->close();
}

void Widget::on_btnSendMsg_clicked()
{
if (!m_socket)
return;

QString msg = ui->textEditSend->toPlainText();
m_socket->write(msg.toLocal8Bit());
}

界面如图:

在这里插入图片描述

总结

本文只简单演示了 TCP 通信的基本原理。服务端只允许一个客户端连接。然而,一般的 TCP 服务器程序允许多个客户端接入,博主将在其他文章中进行讲解。

举报

相关推荐

0 条评论