当前位置: 首页 > news >正文

4.远程控制网络编程的设计下

语法角度限制单例,不是规范限制,最强的是硬件来保证

单例模式

概念:确保一个类只有一个实例(就要求它的构造方法一定不能是public公开的, 即不能被外界进行实例化, 那它的构造方法只能是private, 接着,他只有一个实例, 这个实例属于当前类, 即这个实例是当前类的类成员变量,及类静态成员, 那我们知道类变量就是静态变量, 用static修饰, 所以上半句话, 我们就可以想象出来, 这种设计模式要求构造方法是private, 并且拥有一个当前类的静态成员变量), 而且自行实例化并向整个系统提供这个实例(后面他要求向整个系统提供这个实例, 即我们要再提供一个静态的方法, 向外界提供当前类的实例, 当前类只能在内部进行实例化, 不能放到外面去) 单例模式的主要作用是确保一个类只有一个实例存在, 比如说序列号生成器、Web页面的计数器等等都可以使用单例模式, 同时如果创建某个对象需要消耗较多资源的话, 比如访问IO、 或者数据库资源的时候, 我们也可以使用单例模式来减少资源的消耗

其实单例模式可以分为两种, 饿汉式和懒汉式,饿汉式是什么呢, 即在类加载的时候就进行实例化

private:CServerSocket(){static CServerSocket* m_instance = new CServerSocket();}

懒汉式: 在刚开始,即在类加载的时候不进行实例化, 在第一次使用的时候在进行实例化

public:static CServerSocket* getInstance() {if (m_instance == NULL) { //静态函数没有this指针,无法直接访问成员变量,静态成员函数可以访问静态成员变量m_instance = new CServerSocket();}return m_instance;}

下面是代码

//ServerSocket.h
#pragma once
#include "pch.h"
#include "framework.h"class CServerSocket
{
public:static CServerSocket* getInstance() { //外部访问接口,类静态函数,可以直接调用if (m_instance == NULL) { //静态函数没有this指针,无法直接访问成员变量,所以m_instance定义为static类型m_instance = new CServerSocket();}return m_instance;}
private: //单例模式,希望这个类只被构造和析构一次CServerSocket& operator=(const CServerSocket& ss) {} //赋值也要设置为私有CServerSocket(const CServerSocket&) {} //复制构造函数也要设置为私有CServerSocket() { //构造函数肯定要私有if (InitSockEnv() == FALSE) {MessageBox(NULL, _T("无法初始化套接字环境,请检查网络设置!"), _T("初始化错误!"), MB_OK | MB_ICONERROR);exit(0);}}~CServerSocket() {//析构函数肯定要私有WSACleanup();}BOOL InitSockEnv() {WSADATA data;if (WSAStartup(MAKEWORD(1, 1), &data) != 0) { //TODO:返回值处理}return FALSE;}return TRUE;}static CServerSocket* m_instance; //声明一个静态指针变量,必须类外初始化(),如果是静态成员变量,外面不好初始化,指针赋值NULL就可以了,静态成员变量在类内声明,声明的作用只是限制静态成员变量作用域static void releaseInstance() { //静态成员函数只能访问静态成员(因为没有this指针所以不能访问普通成员变量或者函数)if (m_instance != NULL) {CServerSocket* tmp = m_instance;m_instance = NULL;delete tmp;}}class CHelper {public:CHelper() {CServerSocket::getInstance();}~CHelper() {CServerSocket::releaseInstance(); //通过类来调用只能是静态成员函数}};static CHelper m_helper;//声明,静态类的目的是为了将其变成全局变量
};

为什么m_instance必须是指针不是对象?

因为如果是对象的话,其他地方就调用不了,指针是全局的,不是对象没有问题

这种方法可以保证执行构造函数,但是如何执行析构函数呢?

再建一个私有的类,在这个类的析构里面delete指针m_instance,这个类定义的对象必须要是static的,因为要在.cpp文件里面调用

//ServerSocket.cpp
#include "pch.h"
#include "ServerSocket.h"CServerSocket* CServerSocket::m_instance = NULL; //静态指针变量的类外初始化(必须)CServerSocket::CHelper CServerSocket::m_helper; //保证的全局唯一,其他任何人想调都调不了CServerSocket* pserver = CServerSocket::getInstance(); //指针是全局的,不是对象没有问题

接下来将socket初始化最好也封装起来(这就不用放private里面了)

//ServerSocket.cppbool InitSocket() {//TODO,校验if (m_sock == -1) return false;sockaddr_in serv_adr;memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = INADDR_ANY; //可能不是单网卡,可能有很多网卡,多IPserv_adr.sin_port = htons(9527);//绑定if (bind(m_sock, (sockaddr*)&serv_adr, sizeof(serv_adr)) == -1) {return false;}//TODO;//TODO;if (listen(m_sock, 1) == -1) { //1对1的,队列里面存一个就行return false;}return true;}

对于m_sock这样的SOCKET变量,应该放在成员变量里面,然后在构造函数里面初始化

private: //单例模式,希望这个类只被构造和析构一次SOCKET m_sock,m_client;
	CServerSocket() { //构造函数肯定要私有m_client = -1; //一开始客户端的句柄是没有的if (InitSockEnv() == FALSE) {MessageBox(NULL, _T("无法初始化套接字环境,请检查网络设置!"), _T("初始化错误!"), MB_OK | MB_ICONERROR);exit(0);}m_sock = socket(PF_INET, SOCK_STREAM,0); //这个句柄是会有的}CServerSocket(const CServerSocket& ss) {m_sock = ss.m_sock;m_client = ss.m_client;} //复制构造函数也要设置为私有

给客户端的句柄的收到也定义一个函数

	bool AcceptClient() {//read文件sockaddr_in client_adr;int cli_sz = sizeof(client_adr);m_client = accept(m_sock, (sockaddr*)&client_adr, &cli_sz);if (m_client == -1) return false;return true;//recv(serv_sock, buffer, sizeof(buffer), 0);//send(serv_sock, buffer, sizeof(buffer), 0);}

然后就是处理收到信息的函数

	int DealCommand() { //无限循环if (m_client == -1) return -1; //断开连接了char buffer[1024] = "";while (true) {int len = recv(m_client, buffer, sizeof(buffer), 0); //index是用掉的if (len <= 0) {return -1;}}}

Send需要一个函数

	bool Send(const char* pData, int nSize) {return send(m_client, pData, nSize, 0)>0;}

接下来是server端主函数需要的代码

        else{// TODO: socket//套接字初始化//server;CServerSocket* pserver = CServerSocket::getInstance(); //创建单例int count = 0;if (CServerSocket::getInstance() != NULL) {if (pserver->InitSocket() == false) {MessageBox(NULL,_T("网络初始化异常,未能成功初始化,请检查网络状态!"),_T("网络初始化"),MB_OK | MB_ICONERROR);exit(0);}if (pserver->AcceptClient() == false) {if (count >= 3) {MessageBox(NULL, _T("太多次错误,结束程序"), _T("接入用户失败"), MB_OK | MB_ICONERROR);exit(0);}MessageBox(NULL, _T("无法正常接入用户,自动重试"), _T("接入用户失败"), MB_OK | MB_ICONERROR);count++;}int ret = pserver->DealCommand();}

文章转载自:

http://5rq8w9w8.ppqjh.cn
http://0vGXDNuc.ppqjh.cn
http://bOgrZnk8.ppqjh.cn
http://no1mwbgs.ppqjh.cn
http://rY4OOU3N.ppqjh.cn
http://E6OTKtOA.ppqjh.cn
http://iYCO7rET.ppqjh.cn
http://Ytqypqu8.ppqjh.cn
http://4R5f8ktX.ppqjh.cn
http://8zwdIZ42.ppqjh.cn
http://oGtSHT7y.ppqjh.cn
http://d1bt5gNe.ppqjh.cn
http://Kf0L1Ihp.ppqjh.cn
http://WfkTMAHI.ppqjh.cn
http://HskmXfsV.ppqjh.cn
http://SbhAF3BJ.ppqjh.cn
http://qHrujHB1.ppqjh.cn
http://NtwBfRPN.ppqjh.cn
http://kAQ6rQnK.ppqjh.cn
http://ozYdpKUZ.ppqjh.cn
http://FG0J4Iv6.ppqjh.cn
http://bBAXrpMZ.ppqjh.cn
http://BhvyvzSf.ppqjh.cn
http://K7q1WR9Z.ppqjh.cn
http://UjxgoeUl.ppqjh.cn
http://flCOyaqu.ppqjh.cn
http://rwt8szyq.ppqjh.cn
http://jUhcffw3.ppqjh.cn
http://DxhfZ2ap.ppqjh.cn
http://NKuBr9AM.ppqjh.cn
http://www.dtcms.com/a/377307.html

相关文章:

  • 【Docker Buildx】docker buildx本地构建多架构镜像,拉取镜像时的网络延迟问题(已解决)
  • UNet改进(38):基于Agent-based Sparsification模型压缩解析
  • 零代码部署工业数据平台:TRAE + TDengine IDMP 实践
  • Django全栈班v1.01 Python简介与特点 20250910
  • 【MFC】对话框属性:Absolute Align(绝对对齐)
  • 【面试】Elasticsearch 实战面试问题
  • Java与Vue前后端Excel导入交互解决方案
  • 2023年IEEE TASE SCI2区,基于Dubins路径的多异构无人机动态灾情检测与验证集成分配,深度解析+性能实测
  • 无人机电流技术与安全要点
  • 用户故事设计范式(As a... I want to... So that...)
  • 技嘉B760+i5 12400F+ 华硕tuf rtx5060装机配置方案|仅供参考2025.09.10
  • PSO-BP粒子群优化BP神经网络回归预测+SHAP分析+PDP部分依赖图,可解释机器学习,Matlab代码
  • HarmonyOS编写教师节贺卡
  • 点晴免费OA系统为企业提供高效办公的解决方案
  • Python:Scapy 网络交互与安全的工具库
  • web中的循环遍历
  • 行业学习【电商】:腾讯视频、携程算“电商”吗?
  • 使用 `matchMedia()` 方法检测 JavaScript 中的媒体状态
  • Record和as keyof typeof断言的使用
  • 大数据电商流量分析项目实战:Day 1-1 Linux基础(补充)
  • 【非对称密码算法“克星”】Shor 算法如何撬动互联网安全根基
  • 权重衰减与暂退法
  • 知识图谱——图数据库与项目构建
  • docker 拉取本地镜像
  • CSS(引入、权重、特指度、继承)
  • RMS设备检修管理系统_HawkEye智能运维平台_璞华大数据
  • Shell编程:检测主机ip所在网段内其他在线ip
  • PMC转PXIE转接卡
  • 在Windows上搭建GPU版本PyTorch运行环境的详细步骤
  • LayaAir鼠标(手指)控制相机旋转,限制角度