(二) 用QWebSocket 实现服务端和客户端(详细代码直接使用)
目录
前言
一、服务器的代码:
1、服务器的思路
2、具体服务器的代码示例
二、客户端的代码:
1、客户端的思路(和服务器类似)
2、具体客户端的代码示例
前言
要是想了解QWebSocket的详细知识,还得移步到上一篇文章:
WebSocket 详解,以及用QWebSocket 实现服务端和客户端(含代码例子)-CSDN博客WebSocket 详解,以及用QWebSocket 实现服务端和客户端(含代码例子)-CSDN博客
本篇文章主要讲解如何利用QWebSocket 实现服务和客户之间的通讯
一、服务器的代码:
1、服务器的思路
(1)首先创建了一个服务器的基类,主要实现了服务类的基本接口:
1、创建服务器:new QWebSocketServer
2、监听:listen
m_pWebSocketServer->listen(QHostAddress::LocalHost, mPort);//端口号
3、有新的连接,收到这个信号:QWebSocketServer::newConnection
4、获得新的客户端:nextPendingConnection
5、接收到信息时候,收到信号:QWebSocket::binaryMessageReceived
6、断开连接,收到信号:QWebSocket::disconnected注意:数据的接收和发送,有两种格式,二进制和文本的,具体按照实际需要的来选择;
(2)在服务器的基类上,封装一个具体使用的类,这个类,主要是添加了QThread,创建一个子线程来进行服务器的开启,监听和接收数据,不会影响主线程的事件。
2、具体服务器的代码示例
接收和发送的数据,以二进制为例
(1)服务器基类:
服务器基类的头文件:
1)开启一个端口号为“9000”的服务器
2)监听的网路是:QHostAddress::Any
QHostAddress::Any表示服务端监听所有可用的网络接口。
它是一个特殊的IP地址,表示服务端可以接受来自任何IP地址的连接请求。
这通常用于在一个计算机上运行多个网络服务时,让服务端能够监听所有可用的网络接口,以便接受来自不同网络接口的连接请求。
注意:也可以监听具体的IP地址:
例如:QHostAddress(strLocalHostIp)
#ifndef WEBSOCKETSERVERBASE_H
#define WEBSOCKETSERVERBASE_H#include <QObject>
#include <QtWebSockets>QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
QT_FORWARD_DECLARE_CLASS(QString)class WebsocketServerBase : public QObject
{Q_OBJECT
public:explicit WebsocketServerBase(QString serverName, quint16 port, QObject *parent = 0);virtual ~WebsocketServerBase();signals://客户端发来的数据void sigProcessServerMessage(const QByteArray &data);public slots://发送数据给客户端void slotSendToAllClients(const QByteArray &data);//启动websocket服务器void slotStartServer();private slots://处理新接入的连接void slotNewConnection();//处理链接断开的事件void slotSocketDisconnected();//接收数据,并转发void slotProcessBinaryMessage(const QByteArray &message);public://检测是否存在客户端bool hadClients();private:QWebSocketServer *m_pWebSocketServer = nullptr;QList<QWebSocket *> m_clients;unsigned short m_nPort = 9000;QString m_strServerName = "server";
};#endif // WEBSOCKETSERVERBASE_H
服务器基类的源文件:
#include "websocketserverbase.h"#include<QDebug>static QString getIdentifier(QWebSocket *peer)
{return QStringLiteral("%1:%2").arg(peer->peerAddress().toString(),peer->origin());
}WebsocketServerBase::WebsocketServerBase(QString serverName, quint16 port, QObject *parent): QObject(parent),m_nPort(port),m_strServerName(serverName)
{
}WebsocketServerBase::~WebsocketServerBase()
{ if(m_pWebSocketServer){m_pWebSocketServer->close();//m_pWebSocketServer->abort();m_pWebSocketServer->deleteLater();}
}//接收到外部发来的信息,转发给客户端
void WebsocketServerBase::slotSendToAllClients(const QByteArray &data)
{qDebug() << __FUNCTION__;for (QWebSocket *pClient : qAsConst(m_clients)) {qDebug() << "data: " << data;pClient->sendBinaryMessage(data);}
}bool WebsocketServerBase::hadClients()
{return m_clients.size()>0;
}void WebsocketServerBase::slotStartServer()
{if(m_pWebSocketServer)return;m_pWebSocketServer = new QWebSocketServer(m_strServerName, QWebSocketServer::NonSecureMode, this);if (m_pWebSocketServer->listen(QHostAddress::Any, m_nPort)){connect(m_pWebSocketServer, &QWebSocketServer::newConnection, this, &WebsocketServerBase::slotNewConnection);qDebug() << "WebSocket is start, port:" << m_nPort;}
}void WebsocketServerBase::slotNewConnection()
{auto pSocket = m_pWebSocketServer->nextPendingConnection();QTextStream(stdout) << getIdentifier(pSocket) << " connected!\n";qDebug() << "client connected!";pSocket->setParent(this);//二进制数据的接收connect(pSocket, &QWebSocket::binaryMessageReceived, this, &WebsocketServerBase::slotProcessBinaryMessage);connect(pSocket, &QWebSocket::disconnected, this, &WebsocketServerBase::slotSocketDisconnected);m_clients << pSocket;
}void WebsocketServerBase::slotSocketDisconnected()
{QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());QTextStream(stdout) << getIdentifier(pClient) << " disconnected!\n";if (pClient){m_clients.removeAll(pClient);pClient->deleteLater();}
}//接收客户端发来的数据,并转发出去
void WebsocketServerBase::slotProcessBinaryMessage(const QByteArray &data)
{qDebug() << __FUNCTION__ << " data:" << data;emit sigProcessServerMessage(data);//test//slotSendToAllClients(data);
}
(2)将服务器基类封装,改造下:(外面可以直接使用这个类进行通讯)
改造后服务器的头文件:
此处本例是使用回调函数将结果抛给上一层调用者,在qt里,完全可以用信号槽代替的。
#ifndef READERWEBSOCKETSERVER_H
#define READERWEBSOCKETSERVER_H#include <QObject>
#include "Singleton.h"// 回调函数,将websocket的结果抛给上层
typedef void(*recvMsgToSerial)(const QByteArray &byteArray);class WebsocketServerBase;
class ReaderWebsocketServer : public QObject, public Singleton<ReaderWebsocketServer>
{Q_OBJECTfriend class Singleton<ReaderWebsocketServer>;public:explicit ReaderWebsocketServer(QObject *parent = 0);virtual ~ReaderWebsocketServer();public:// 设置回调函数void setCallBack(recvMsgToSerial pFunc, void* pUser = NULL);// 接收串口发来数据,转发给客户端bool sendData(const QByteArray &byteArray);signals://转发数据给客户端void sigSendToAllClients(const QByteArray &data);private slots://处理客户端发来的数据,转发给需要的地方void slotProcessServerMessage(const QByteArray &data);private:WebsocketServerBase* m_pWsServer = nullptr;QThread* m_thdWsServer = nullptr;void* m_pUser; // 返回回调的对象recvMsgToSerial m_pRecvMsgToSerial; // 回调
};#endif // READERWEBSOCKETSERVER_H
改造后服务器的源文件:
#include "readerwebsocketserver.h"#include <QThread>
#include <cstring>
#include "websocketserverbase.h"ReaderWebsocketServer::ReaderWebsocketServer(QObject *parent): QObject(parent)
{m_thdWsServer = new QThread();m_pWsServer = new WebsocketServerBase("reader", 9000);m_pWsServer->moveToThread(m_thdWsServer);connect(m_pWsServer, &WebsocketServerBase::sigProcessServerMessage, this, &ReaderWebsocketServer::slotProcessServerMessage);connect(this, &ReaderWebsocketServer::sigSendToAllClients, m_pWsServer, &WebsocketServerBase::slotSendToAllClients);connect(m_thdWsServer, &QThread::started, m_pWsServer, &WebsocketServerBase::slotStartServer);connect(m_thdWsServer, &QThread::finished, m_pWsServer, &WebsocketServerBase::deleteLater);connect(m_thdWsServer, &QThread::finished, m_thdWsServer, &WebsocketServerBase::deleteLater);m_thdWsServer->start();
}ReaderWebsocketServer::~ReaderWebsocketServer()
{if(m_thdWsServer){m_thdWsServer->quit();m_thdWsServer->wait();}if(m_pWsServer){m_pWsServer->deleteLater();}
}void ReaderWebsocketServer::setCallBack(recvMsgToSerial pFunc, void *pUser)
{if (nullptr != pFunc)m_pRecvMsgToSerial = pFunc;if (nullptr != pUser)m_pUser = pUser;
}//接收串口发来数据,转发给客户端
bool ReaderWebsocketServer::sendData(const QByteArray &byteArray)
{bool hadBnode = m_pWsServer->hadClients();if (hadBnode){emit sigSendToAllClients(byteArray);}
}//处理客户端发来的数据,转发给需要的地方
void ReaderWebsocketServer::slotProcessServerMessage(const QByteArray &byteArray)
{qDebug() << __FUNCTION__ ;m_pRecvMsgToSerial(byteArray);
}
二、客户端的代码:
1、客户端的思路(和服务器类似)
(1)首先创建了一个客户端的基类,主要实现了客户端的基本接口:
(2)在客户端基类上,封装一个具体使用的类:(外面可以直接使用这个类进行通讯)
这个类,主要是添加了QThread 和QTimer,QThread 创建一个子线程来进行服务器的开启,监听和接收数据,不会影响主线程的事件;QTimer主要是发心跳包,实现断开重连机制;
2、具体客户端的代码示例
接收和发送的数据,以二进制为例
(1)客户端基类:
客户端基类的头文件:
/** @Description: websocket客户端,用于与中间件通信*/#pragma once
#include <QObject>
#include <QByteArray>class QTimer;
class QWebSocket;
class WebSocketBase : public QObject
{Q_OBJECT
public:WebSocketBase(QObject *parent = nullptr);~WebSocketBase();void setWebSocketUrl(QString strUrl="");bool getConnectStatus();int RecvFrom(QByteArray& byteArray);signals:void sigClientBinaryMessageReceived(const QByteArray &byteArray); //借用websocket的信号函数public slots:void slotCreateDataRecWS();//创建websocket连接void slotSendBinaryMessageMessage(const QByteArray &byteArray);void slotReconnect(); /*-<周期重连函数 */void slotActiveReconnect();private slots:void slotOnConnected(); /*-<socket建立成功后,触发该函数 */void slotOnBinaryMessageReceived(const QByteArray &byteArray); /*-<收到Sev端的数据时,触发该函数 */void slotOnDisConnected(); /*-<socket连接断开后,触发该函数 */private:QWebSocket *m_pDataRecvWS; /*-<websocket类 */QTimer *m_pTimer; /*-<周期重连Timer */QString m_strURL; /*连接URL*/bool m_bConnectStatus; /*-<websocket连接状态,连接成功:true;断开:false */QByteArray m_byteArray;
};
客户端基类的源文件:
#include "WebSocketBase.h"
#include <QWebSocket>
#include <QTimer>
#include <QByteArray>
#include <cstring>WebSocketBase::WebSocketBase(QObject *parent) : QObject(parent),m_pDataRecvWS(nullptr),m_pTimer(nullptr),m_strURL(""),m_bConnectStatus(false),m_byteArray("")
{}WebSocketBase::~WebSocketBase()
{m_pTimer->stop();m_pTimer->deleteLater();m_pDataRecvWS->abort();m_pDataRecvWS->deleteLater();
}void WebSocketBase::setWebSocketUrl(QString strUrl)
{m_strURL = strUrl;if(m_strURL.isEmpty()){m_strURL = "127.0.0.1";}
}bool WebSocketBase::getConnectStatus()
{return m_bConnectStatus;
}int WebSocketBase::RecvFrom(QByteArray &byteArray)
{byteArray = m_byteArray;m_byteArray.clear();return byteArray.size();
}void WebSocketBase::slotCreateDataRecWS()
{if(nullptr == m_pTimer){m_pTimer = new QTimer();}qDebug() << "Server Address" << m_strURL;if(m_pDataRecvWS == nullptr){m_pDataRecvWS = new QWebSocket();connect(m_pDataRecvWS, &QWebSocket::disconnected, this, &WebSocketBase::slotOnDisConnected);connect(m_pDataRecvWS, &QWebSocket::binaryMessageReceived, this, &WebSocketBase::slotOnBinaryMessageReceived);connect(m_pDataRecvWS, &QWebSocket::connected, this, &WebSocketBase::slotOnConnected);connect(m_pTimer, &QTimer::timeout, this, &WebSocketBase::slotReconnect);m_pDataRecvWS->open(QUrl(m_strURL));}
}void WebSocketBase::slotSendBinaryMessageMessage(const QByteArray &message)
{if (m_pDataRecvWS)m_pDataRecvWS->sendBinaryMessage(message);
}void WebSocketBase::slotActiveReconnect()
{qDebug("try to Active Reconnect!!!");if(m_pDataRecvWS != nullptr){m_bConnectStatus = false;m_pDataRecvWS->abort();qDebug("Exec Active Reconnect!");m_pDataRecvWS->open(QUrl(m_strURL));}return;
}void WebSocketBase::slotReconnect()
{qDebug() << "try to reconnect:" << m_strURL;m_pDataRecvWS->abort();m_pDataRecvWS->open(QUrl(m_strURL));
}void WebSocketBase::slotOnConnected()
{qDebug("WebSocketBase websocket is already connect!");m_bConnectStatus = true;m_pTimer->stop();qDebug() << "Address:" << m_strURL;
}void WebSocketBase::slotOnDisConnected()
{qDebug() << "Address is disconnected:" << m_strURL;m_bConnectStatus = false;m_pTimer->start(3000);/*-<当连接失败时,触发重连计时器,设置计数周期为3秒 */
}void WebSocketBase::slotOnBinaryMessageReceived(const QByteArray& byteArray)
{m_byteArray = byteArray;
}
(2)将客户端基类封装,改造下:(外面可以直接使用这个类进行通讯)
改造后客户端头文件:
/** @Description: websocket客户端,用于与中间件通信*/
#pragma once#include <QObject>
#include <QCoreApplication>#include "Singleton.h"class WebSocketBase;
class QTimer;class WsReaderClient : public QObject, public Singleton<WsReaderClient>
{Q_OBJECTfriend class Singleton<WsReaderClient>;public:WsReaderClient(QObject *parent = nullptr);~WsReaderClient();public:void SendTo(const QByteArray &byteArray);int RecvFrom(QByteArray& byteArray);bool getConnectStatus();signals://转发数据给servervoid sigSendToServer(const QByteArray &byteArray);public slots://接收服务器数据void slotRecvServerData(const QByteArray &byteArray);//发送服务器心跳包void slotHeartBeatToServer();private:void readConfig();private:WebSocketBase* m_wsReaderClient;QThread* m_thdReaderClient;QTimer *m_pTimerReader;int m_nHeartBeatTimeOutReader;QString m_URL = "";
};
改造后客户端源文件:
#include "WsReaderClient.h"#include <QWebSocket>
#include <QTimer>
#include <QThread>
#include <QByteArray>
#include <cstring>
#include <QSettings>#include "WebSocketBase.h"WsReaderClient::WsReaderClient(QObject *parent): QObject(parent)
{readConfig();m_thdReaderClient = new QThread();m_wsReaderClient = new WebSocketBase();m_wsReaderClient->setWebSocketUrl(m_URL);m_wsReaderClient->moveToThread(m_thdReaderClient);connect(m_thdReaderClient, &QThread::started, m_wsReaderClient, &WebSocketBase::slotCreateDataRecWS);connect(this, &WsReaderClient::sigSendToServer, m_wsReaderClient, &WebSocketBase::slotSendBinaryMessageMessage);//connect(this, &WsReaderClient::sigReconnectServer, m_wsReaderClient, &WebSocketBase::slotActiveReconnect);connect(m_thdReaderClient, &QThread::finished, m_wsReaderClient, &WebSocketBase::deleteLater);connect(m_thdReaderClient, &QThread::finished, m_thdReaderClient, &QThread::deleteLater);m_thdReaderClient->start();m_pTimerReader = new QTimer(this);connect(m_pTimerReader, &QTimer::timeout, this, &WsReaderClient::slotHeartBeatToServer);//m_nHeartBeatTimeOutKeyBoard = 0;m_pTimerReader->start(10*1000);
}WsReaderClient::~WsReaderClient()
{m_pTimerReader->stop();m_pTimerReader->deleteLater();if(m_wsReaderClient){delete m_wsReaderClient;m_wsReaderClient = nullptr;}if(m_pTimerReader){delete m_pTimerReader;m_pTimerReader = nullptr;}
}void WsReaderClient::slotHeartBeatToServer()
{//todo
}void WsReaderClient::readConfig()
{// "/mnt/hgfs/SharedFiles/shanxi/Reader/linux_readerTest/bin/libReaderApi.so";QString appPath = QCoreApplication::applicationDirPath();qDebug() << "appPath=" << appPath;QString path = appPath + "/ReaderConfig.ini";QSettings settings(path, QSettings::IniFormat);m_URL = settings.value("Communication/ipAddr").toString();qDebug() << "m_URL=" << m_URL;
}void WsReaderClient::SendTo(const QByteArray &data)
{emit sigSendToServer(data);
}int WsReaderClient::RecvFrom(QByteArray &byteArray)
{return m_wsReaderClient->RecvFrom(byteArray);
}bool WsReaderClient::getConnectStatus()
{return m_wsReaderClient->getConnectStatus();
}
相关文章:
(二) 用QWebSocket 实现服务端和客户端(详细代码直接使用)
目录 前言 一、服务器的代码: 1、服务器的思路 2、具体服务器的代码示例 二、客户端的代码: 1、客户端的思路(和服务器类似) 2、具体客户端的代码示例 前言 要是想了解QWebSocket的详细知识,还得移步到上一篇文…...
关于我在配置zookeeper出现,启动成功,进程存在,但是查看状态却没有出现Mode:xxxxx的问题和我的解决方案
在我输入:zkServer.sh status 之后出现报错码. 报错码: ZooKeeper JMX enabled by default Using config: /opt/software/zookeeper/bin/../conf/zoo.cfgClient port found: 2181. Client address: localhost. Error contacting service. It is probably not runni…...
react及相关面试问题汇总
目录 1、什么是React?它的特点是什么? 2、解释一下虚拟DOM(Virtual DOM)的概念以及它的工作原理。 3、什么是组件(Component)?如何定义一个React组件? 4、什么是JSX?它与HTML的区别是什么?如何在React中…...
QT4到QT5移植出现的一些问题
转自:QT4到QT5移植出现的一些问题_西门子3gl qt5 许可证-CSDN博客 在上述作者基础上修改: 一、问题1:头文件的问题 1、QtGui/QApplication: No such file or directory 1.1错因 原因是Qt5源文件位置的改动 1.2解决 pro文件里࿰…...
【可解释AI】Alibi explain: 解释机器学习模型的算法
Alibi explain: 解释机器学习模型的算法 可解释人工智能简介Alibi特点算法Library设计展望参考资料 今天介绍Alibi Explain,一个开源Python库,用于解释机器学习模型的预测(https://github.com/SeldonIO/alibi)。该库具有最先进的分类和回归模型可解释性算…...
No191.精选前端面试题,享受每天的挑战和学习
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...
ROS基础—vscode创建工作空间
1、创建ROS工作空间 首先打开ubuntu的终端,接着依次输入如下的命令行; mkdir -p xxx_ws/src(必须得有 src) cd xxx_ws catkin_make当然我一般是新建一个叫做demo的工作空间,如 mkdir -p demo04_ws/src 2、启动vscode cd xxx_ws code . …...
机器学习复习(待更新)
01绪论 (1)机器学习基本分类: 监督学习(有标签)半监督学习(部分标签,找数据结构)无监督学习(无标签,找数据结构)强化学习(不断交互&…...
taro(踩坑) npm run dev:weapp 微信小程序开发者工具预览报错
控制台报错信息: VM72:9 app.js错误: Error: module vendors-node_modules_taro_weapp_prebundle_chunk-JUEIR267_js.js is not defined, require args is ./vendors-node_modules_taro_weapp_prebundle_chunk-JUEIR267_js.js 环境: node 版本&#x…...
3. 深度学习——损失函数
机器学习面试题汇总与解析——损失函数 本章讲解知识点 什么是损失函数?为什么要使用损失函数?详细讲解损失函数本专栏适合于Python已经入门的学生或人士,有一定的编程基础。 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。 本专栏针对面试题答案进行了优化…...
交叉编译 openssl
要在 x86 平台上编译适用于 aarch64 架构的 OpenSSL 动态库,你需要使用交叉编译工具链。可以按照以下步骤进行: 安装 aarch64 交叉编译工具链: $ sudo apt-get install gcc-aarch64-linux-gnu g-aarch64-linux-gnu 这将安装 aarch64 交叉编…...
C++文件的读取和写入
1、C对txt文件的读,ios::in #include<iostream> #include<fstream> using namespace std;int main() {ifstream ifs;ifs.open("test.txt",ios::in);if(!ifs.is_open()){cout<<"打开文件失败!"<<endl;}char…...
住宅IP、家庭宽带IP以及原生IP,它们有什么区别?谷歌开发者账号应选择哪种IP?
IP地址(Internet Protocol Address)是互联网协议地址的简称,是互联网通信的基础,互联网上每一个网络设备的唯一标识符每个在线的设备都需要一个IP地址,这样才能在网络中找到它们并进行数据交换。 IP地址有很多种类型&…...
Linux内核分析(十三)--内存管理之I/O交换与性能调优
目录 一、引言 二、page cache ------>2.1、file-backed ------>2.2、匿名页(Anonymous page) ------>2.3、读写方式 ------>2.4、常驻内存 三、页面回收 ------>3.1、LRU算法 ------>3.2、嵌入式系统的zRAM 四、内存性能调优 ------>4.1、存储…...
前端使用webscoket
前端 <template><div class"wrap"><button click"socketEmit">连接Socket</button><button click"socketSendmsg">发送数据</button></div> </template><script> export default {data(…...
centos安装Git
一开始使用yum -y install git出来的版本比较低。 1.yum安装gityum -y install git 2.查看git的版本git --version 3.删除git(版本过低)yum remove -y git 后来通过源码编译后安装: 使用安装包安装: 1.下载安装包:h…...
网络编程 初探windows编程
目录 一、什么是Winodws编程 二、开发环境搭建以及如何学习 三、VA助手安装 四、第一个Win32程序 五、窗口类句柄/窗口类对象 六、Winodws消息循环机制 七、Windows数据类型 一、什么是Winodws编程 Windows 编程指的是在 Microsoft Windows 操作系统上进行软件开发的过…...
Vue3 ref函数和reactive函数
一、ref函数 我们在setup函数中导出的属性和方法虽然能够在模板上展示出来,但是并没有给属性添加响应式,因此,我们需要使用ref函数来为我们的数据提供响应式。 (一)引入ref函数 import { ref } from "vue"…...
docker常用命令详解
1. Image常见操作 (1)查看本地image列表 docker images docker image ls (2)获取远端镜像 docker pull (3)删除镜像[注意此镜像如果正在使用,或者有关联的镜像,则需要先处理完] docker image rm imageid docker rmi -f imageid docker rmi -f $(docker …...
采集Prestashop独立站采集Prestashop独立站
import java.net.URL 这一行导入了Java.net包中的URL类,这个类在处理URL链接时非常有用。 import org.jsoup.Jsoup 这一行导入了Jsoup库,它是一个强大的HTML和XML文档解析库,我们可以使用它来解析网页内容。 import org.jsoup.nodes.Docume…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...
数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...
Redis专题-实战篇一-基于Session和Redis实现登录业务
GitHub项目地址:https://github.com/whltaoin/redisLearningProject_hm-dianping 基于Session实现登录业务功能提交版本码:e34399f 基于Redis实现登录业务提交版本码:60bf740 一、导入黑马点评后端项目 项目架构图 1. 前期阶段2. 后续阶段导…...
