【iOS逆向与安全】好用的一套 TCP 类

 初始化

//页面
%hook xxxxxxxViewController//- (void)viewWillAppear:(BOOL)animated{
//NSLog(@"View Will Appear,再次进入刷新");
- (void)viewDidLoad{//启动tcp[[Xddtcp sharedTcpManager] connectServer] ;}

 发送数据

//发送数据 [[Xddtcp sharedTcpManager] sendDataToServer:[@"MyiPhone" dataUsingEncoding:NSUTF8StringEncoding]] ;

源码类

//
//  Xddtcp.m
//  YFX_ScoketForClientDemo
//
//  Created by adminxdd on 2020/8/20.
//  Copyright © 2020 fangxue. All rights reserved.
//#import "Xddtcp.h"#define WSELF __weak typeof(self) wself = self;/** 主线程异步队列 */
#define Dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}//@implementation Xddtcp
@interface Xddtcp() <GCDAsyncSocketDelegate>/** 心跳计时器 */
@property (nonatomic, strong) NSTimer *heartBeatTimer;/** 没有网络的时候检测网络定时器 */
@property(nonatomic,strong)NSTimer*netWorkTestingTimer;/** 存储要发送给服务端的数据 */
@property (nonatomic, strong) NSMutableArray *sendDataArray;/** 数据请求队列(串行队列) */
@property (nonatomic, strong) dispatch_queue_t queue;/** 重连时间 */
@property (nonatomic, assign) NSTimeInterval reConnectTime;/** 用于判断是否主动关闭长连接,如果是主动断开连接,连接失败的代理中,就不用执行 重新连接方法 */
@property (nonatomic, assign) BOOL isActivelyClose;/** 缓存区域 */
@property (nonatomic, strong) NSMutableData *readBuf;@end@implementation Xddtcp#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
#pragma mark ----单利------/** 单利 */
+ (instancetype)sharedTcpManager{static Xddtcp*_instace =nil;static dispatch_once_t onceToken;dispatch_once(&onceToken,^{_instace = [[self alloc]init];NSLog(@"TCP 单利实例化!");});return _instace;
}
#pragma mark ----初始化------/** 初始化 */
- (instancetype)init{self= [super init];if(self){self.reConnectTime = 0;self.isActivelyClose = NO;self.queue = dispatch_queue_create("BF",NULL);self.sendDataArray = [[NSMutableArray alloc] init];//        self.mRecvPacket = [JHreceivePacket sharedManager];//        self.deviceListArr = [[NSMutableArray alloc] init];//        DLogInfo(@"初始化!");}return self;
}#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥#pragma mark --- 心跳计时器处理 -----/** 心跳计时器初始化 */
- (void)initHeartBeat{//心跳没有被关闭if(self.heartBeatTimer){return;}[self destoryHeartBeat];//连接成功  先发一次 心跳数据 在打开计时器//[[JHSocketData sharedManager] heartbeat];//判断是否打开if([xddTools keyGet:@"isOpenTCP"]&&[[xddTools keyGet:@"isOpenTCP"] isEqualToString:@"已打开"]){[self.asyncTcpSocket writeData:[@"MyiPhone" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];}WSELFDispatch_main_async_safe(^{wself.heartBeatTimer  = [NSTimer timerWithTimeInterval:30 target:wself selector:@selector(senderheartBeat) userInfo:nil repeats:true];[[NSRunLoop currentRunLoop]addTimer:wself.heartBeatTimer forMode:NSRunLoopCommonModes];});}#pragma mark --- 取消心跳 -----/** 取消心跳 */
- (void)destoryHeartBeat
{WSELFDispatch_main_async_safe(^{if(wself.heartBeatTimer){[wself.heartBeatTimer invalidate];wself.heartBeatTimer =nil;}});
}#pragma mark --- 没有网络的时候开始定时 -- 用于网络检测 -----/** 没有网络,进行网络监测 */
- (void)noNetWorkStartTestingTimer{WSELFDispatch_main_async_safe(^{wself.netWorkTestingTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:wself selector:@selector(noNetWorkStartTesting) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:wself.netWorkTestingTimer forMode:NSDefaultRunLoopMode];});
}#pragma mark --- 取消网络监测 ----/** 取消网络监测 */
- (void)destoryNetWorkStartTesting
{WSELFDispatch_main_async_safe(^{if(wself.netWorkTestingTimer){[wself.netWorkTestingTimer invalidate];wself.netWorkTestingTimer =nil;}});
}#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥#pragma mark --- 发送心跳 ---/** 发送心跳 */
- (void)senderheartBeat{//  和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小[self.asyncTcpSocket writeData:[@"ok" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];//    WSELF;//    Dispatch_main_async_safe(^{////    });
}#pragma mark --- 定时检查网络 ---/** 定时检查网络 */
- (void)noNetWorkStartTesting{//有网络if(AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus != AFNetworkReachabilityStatusNotReachable){//关闭网络检测定时器[self destoryNetWorkStartTesting];//开始重连[self reConnectServer];}}
#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥#pragma mark ----建立连接------/**  建立连接 */-(void)connectServer{self.isActivelyClose = NO;NSError*error =nil;_asyncTcpSocket= [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];NSString* ip       = [xddTools keyGet:@"TCP_IP"];NSString* port_str = [xddTools keyGet:@"TCP_Port"];if([ip isEqualToString:@""]){ip = @"192.168.1.2";[xddTools keySet:@"TCP_IP" v:ip];}if([port_str isEqualToString:@""]){port_str = @"12485";[xddTools keySet:@"TCP_Port" v:port_str];}UInt16 port = [port_str integerValue];//你的ip地址和端口号[_asyncTcpSocket connectToHost:ip onPort:port withTimeout:60 error:&error];if(error) {NSLog(@"TCP连接错误:%@", error);}[self.asyncTcpSocket readDataWithTimeout:-1 tag:0];}#pragma mark --- 重连服务器 ---/** 重连服务器 */
- (void)reConnectServer{if (self.asyncTcpSocket.isConnected) {return;}if (self.reConnectTime > 10240) {self.reConnectTime = 0;return;}WSELF;dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.reConnectTime *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{if(wself.asyncTcpSocket.isConnected){return;}[wself connectServer];NSLog(@"正在重连%f",wself.reConnectTime);if(wself.reConnectTime==0){ //重连时间2的指数级增长wself.reConnectTime=2;} else {wself.reConnectTime*=2;}});NSLog(@"重连服务器!");}#pragma mark ----关闭连接------
/** 关闭连接 */
- (void)disConnectServer {NSLog(@"dealloc");// 关闭套接字self.isActivelyClose = YES;[self.asyncTcpSocket disconnect];//关闭心跳定时器[self destoryHeartBeat];//关闭网络检测定时器[self destoryNetWorkStartTesting];self.asyncTcpSocket = nil;
}#pragma mark ---代理 连接成功 ---
//连接成功
-(void)socket:(GCDAsyncSocket*)sock didConnectToHost:(NSString*)host port:(uint16_t)port
{NSLog(@"TCP连接成功!");//    [self.asyncTcpSocket readDataWithTimeout:-1 tag:index];//      [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];// 存储接收数据的缓存区,处理数据的粘包和断包self.readBuf = [[NSMutableData alloc]init];[self initHeartBeat]; //开启心跳//如果有尚未发送的数据,继续向服务端发送数据if([self.sendDataArray count] >0){[self sendeDataToServer];}
}#pragma mark ---代理 连接失败 ---
//连接失败 进行重连操作
-(void)socketDidDisconnect:(GCDAsyncSocket*)sock withError:(NSError*)err{//用户主动断开连接,就不去进行重连if(self.isActivelyClose){return;}[self destoryHeartBeat]; //断开连接时销毁心跳//判断网络环境if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) //没有网络{[self noNetWorkStartTestingTimer];//开启网络检测定时器}else//有网络{[self reConnectServer];//连接失败就重连}NSLog(@"TCP连接失败!");
}#pragma mark --- 消息发送成功 ---
-(void)socket:(GCDAsyncSocket*)sock didWriteDataWithTag:(long)tag{NSLog(@"TCP发送成功");
}#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥#pragma mark --- 发送数据 ---
-(void)sendDataToServer:(id)data{[self.sendDataArray addObject:data];[self sendeDataToServer];//      [self.asyncTcpSocket  writeData:data withTimeout:60 tag:0];
}#pragma mark --- 发送数据给服务器 详细处理 ---/** 发送数据的详细处理 */
-(void)sendeDataToServer{WSELF//把数据放到一个请求队列中dispatch_async(self.queue, ^{//网络判断  没有网络的情况if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) {//开启网络检测定时器[wself noNetWorkStartTestingTimer];}else{ //有网络情况//判断对象是否存在if(wself.asyncTcpSocket != nil) {//判断TCP是否处于连接状态if(wself.asyncTcpSocket.isConnected) {//判断数据  是否存在if(wself.sendDataArray.count>0) {id sendData = wself.sendDataArray[0];NSLog(@"TCP发送出去的数据: %@",sendData);[self.asyncTcpSocket writeData:sendData withTimeout:30  tag:0];[wself.sendDataArray removeObjectAtIndex:0];if([wself.sendDataArray count] >0){[wself sendeDataToServer];}}}else{//TCP 处于断开状态//主动去重连服务器  连接成功后 继续发送数据[wself reConnectServer];}}else{[wself reConnectServer];}}});
}#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥#pragma mark --- 接收的数据 ---
-(void)socket:(GCDAsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag
{//      sleep(1);//此方法处理数据的黏包或者断包NSLog(@"原始数据%@",data);NSString*msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];NSLog(@"xdd接收的数据 = %@",msg);//断包处理[self didReadData:data];[self.asyncTcpSocket readDataWithTimeout:-1 tag:0];NSDictionary*retDic = [xddTools dictionaryWithJsonString:msg];if(retDic == nil || ! [retDic isKindOfClass:[NSDictionary class]]) {return ;}NSString*type_ = retDic[@"type"];NSString*data_ = retDic[@"data"];NSString*msgid_ = retDic[@"msgid"]?retDic[@"msgid"]:@"test";NSLog(@"xdd接收的数据type_=%@,type_=%@",type_,data_);//开始主线程
//    dispatch_async(dispatch_get_main_queue(), ^{//开始子线程dispatch_async(dispatch_get_global_queue(0, 0), ^{if(type_ && data_ && [type_ isEqualToString:@"1"]){//获取森林信息NSDictionary*dic = [xddTools getMYinfo:data_];BOOL success =  [dic[@"success"] boolValue]; //是否成功NSString*resultDesc = dic[@"resultDesc"];//信息提示NSString*resultCode = dic[@"resultCode"];//返回代码NSString*currentEnergy = dic[@"treeEnergy"][@"currentEnergy"];//当前能量NSDictionary*userEnergy = dic[@"userEnergy"];NSString*loginId = userEnergy[@"loginId"];//3333@qq.comNSString*userId = userEnergy[@"userId"];//2088*****NSString*headPortrait = userEnergy[@"headPortrait"];//头像NSString*displayName = userEnergy[@"displayName"];//昵称 茶NSString*energySummation = userEnergy[@"energySummation"];//合计能量NSString*treeAmount = userEnergy[@"treeAmount"];//证书个数NSDictionary *dicRetInfo = [NSDictionary dictionaryWithObjectsAndKeys:msgid_,@"msgid",type_,@"type",resultCode,@"code",currentEnergy,@"current",energySummation,@"summation",userId,@"userId",loginId,@"loginId",headPortrait,@"png",treeAmount,@"tree",displayName,@"name",nil];NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dicRetInfo] dataUsingEncoding:NSUTF8StringEncoding];//NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dicRetInfo options:NSJSONWritingPrettyPrinted error:nil];[self sendDataToServer:jsonData];}else if(type_ && data_ && ( [type_ isEqualToString:@"2"] || [type_ isEqualToString:@"4"])){NSDictionary*dic;if([type_ isEqualToString:@"2"]){// 查询用户手机 昵称信息dic = [xddTools getiPhoneInfo:data_];}else if([type_ isEqualToString:@"4"]){// 查询用户ID昵称信息dic = [xddTools getuseriDInfo:data_];}NSString*account = dic[@"userAccount"];NSString*userID = dic[@"userID"];NSString*nickl = dic[@"userNicklName"];NSString*name = dic[@"userName"];NSString*status = dic[@"resultStatus"];NSString*Suffix = dic[@"userNameSuffix"];NSString*RealName = dic[@"userRealName"];NSString*gender = dic[@"gender"];//userNameSuffix 实名名字//userRealName 注册名字//gender 性别NSDictionary *dicRetInfo = [NSDictionary dictionaryWithObjectsAndKeys:msgid_,@"msgid",type_,@"type",status,@"status",account,@"account",userID,@"userID",nickl,@"nickl",name,@"name",Suffix,@"Suffix",RealName,@"RealName",gender,@"gender",nil];//625 对方账户存在异常,不能进行当前操作 100 okNSData * jsonData = [[xddTools returnJSONStringWithDictionary:dicRetInfo] dataUsingEncoding:NSUTF8StringEncoding];//NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dicRetInfo options:NSJSONWritingPrettyPrinted error:nil];[self sendDataToServer:jsonData];}else if(type_ && data_ && [type_ isEqualToString:@"3"]){//获取合种二维码信息NSDictionary*dic = [xddTools gethezhongqrCode:data_];//            BOOL success =  [dic[@"success"] boolValue]; //是否成功
//            NSString*resultDesc = dic[@"resultDesc"];//信息提示
//            NSString*resultCode = dic[@"resultCode"];//返回代码// 可变字典 转可变字典NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];[dict002 setObject:msgid_ forKey:@"msgid"];[dict002 setObject:type_ forKey:@"type"];[dict002 removeObjectForKey:@"extInfo"];//            NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dict002 options:NSJSONWritingPrettyPrinted error:nil];[self sendDataToServer:jsonData];}else if(type_ && data_ && [type_ isEqualToString:@"5"]){//获取签名NSDictionary*dic = [xddTools getAlipaysign:retDic];NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];[dict002 setObject:msgid_ forKey:@"msgid"];[dict002 setObject:type_ forKey:@"type"];NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];[self sendDataToServer:jsonData];}else if(type_ && data_ && [type_ isEqualToString:@"6"]){//获取签名NSDictionary*dic = [xddTools getAlipaysignV1:retDic];NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];[dict002 setObject:msgid_ forKey:@"msgid"];[dict002 setObject:type_ forKey:@"type"];NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];[self sendDataToServer:jsonData];}else if(type_ && data_ && [type_ isEqualToString:@"xxx"]){}});}
#pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
#pragma mark --- 黏包 断包处理 ---
-(void) didReadData:(NSData*)data {//断包处理 要根据 你的 数据的 长度标识位的数据 来判断 读到什么地方 才是你完整的数据。根据协议去走_readBuf = [NSMutableData dataWithData:data];// 取出4-8位保存的数据长度,计算数据包长度while(_readBuf.length>=5) {// 头数据为5个字节// 得到数据的ID 和 整个数据的长度NSData *dataLength = [_readBuf subdataWithRange:NSMakeRange(3, 2)];Byte*ByteLength = (Byte*)[dataLength bytes];int headLen = (ByteLength[0] &0x00ff) + ((ByteLength[1] &0x00ff) <<8);NSInteger lengthInteger =0;lengthInteger = (NSInteger)headLen;NSInteger complateDataLength = lengthInteger +6;//算出一个包完整的长度(内容长度+头长度)NSLog(@"已读取数据:缓冲区长度:%ld, 接收长度:%lu  数据长度:%ld ", (long)_readBuf.length, (unsigned long)[data length], (long)complateDataLength);//        NSInteger dataLength = length + 2;if(_readBuf.length>= complateDataLength) {//如果缓存中的数据 够  一个整包的长度NSData*msgData = [_readBuf subdataWithRange:NSMakeRange(0, complateDataLength)];// 处理消息数据NSLog(@"得到完整包数据:%@",msgData);// 从缓存中截掉处理完的数据,继续循环_readBuf= [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(complateDataLength,_readBuf.length- complateDataLength)]];//            [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];}else{// 断包情况,继续读取//            [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];//            [sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据[self.asyncTcpSocket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];return;}[self.asyncTcpSocket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据}}@end
//
//  Xddtcp.h
//  YFX_ScoketForClientDemo
//
//  Created by adminxdd on 2020/8/20.
//  Copyright © 2020 fangxue. All rights reserved.
//#import <Foundation/Foundation.h>
#import "AFNetworkReachabilityManager.h"
NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END#import <Foundation/Foundation.h>#import "GCDAsyncSocket.h"#import "xddTools.h"//@interface SingleTcpCase :NSObject
@interface Xddtcp : NSObject@property(strong,nonatomic)GCDAsyncSocket *asyncTcpSocket;/**  单利初始化 */+(instancetype)sharedTcpManager;/**  建立连接 */-(void)connectServer;/**  关闭连接 */-(void)disConnectServer;/**  发送数据给服务器 */-(void)sendDataToServer:(id)data;@end

配置端口

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"请输入配置信息" message:@"++++++" preferredStyle:UIAlertControllerStyleAlert];//增加取消按钮;[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];//增加确定按钮;[alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {//获取第1个输入框;UITextField *userNameTextField = alertController.textFields.firstObject;//获取第2个输入框;UITextField *passwordTextField = alertController.textFields.lastObject;//NSLog(@"用户名 = %@,密码 = %@",userNameTextField.text,passwordTextField.text);if(userNameTextField.text && ![userNameTextField.text isEqualToString:@""]){[xddTools keySet:@"TCP_IP" v:userNameTextField.text];}if(passwordTextField.text && ![passwordTextField.text isEqualToString:@""]){[xddTools keySet:@"TCP_Port" v:passwordTextField.text];}}]];//定义第一个输入框;[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {textField.placeholder = @"请输入配置IP";textField.text = [xddTools keyGet:@"TCP_IP"];}];//定义第二个输入框;[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {textField.placeholder = @"请输入配置端口";textField.text = [xddTools keyGet:@"TCP_Port"];}];[weakSelf presentViewController:alertController animated:true completion:nil];
+(NSString*)keyGet:(NSString*)k
{NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];return [userDefault objectForKey:k]?[userDefault objectForKey:k]:@"";
//    - objectForKey:
//    - URLForKey:
//    - arrayForKey:
//    - dictionaryForKey:
//    - stringForKey:
//    - stringArrayForKey:
//    - dataForKey:
//    - boolForKey:
//    - integerForKey:
//    - floatForKey:
//    - doubleForKey:
//    - dictionaryRepresentation
}
+(void)keySet:(NSString*)k v:(NSString*)v
{NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];[userDefault setObject:v forKey:k];[userDefault synchronize];
//        - setObject:forKey:
//       - setFloat:forKey:
//       - setDouble:forKey:
//       - setInteger:forKey:
//       - setBool:forKey:
//       - setURL:forKey:
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/88681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

点云从入门到精通技术详解100篇-基于全景图的室内场景点云补全方法(续)

目录 3.3 模型训练及实验评估 3.3.1 模型训练 3.3.2实验评估 4 基于自

Redis集群架构搭建——主从、哨兵、集群

上一篇文章Ubuntu上通过源码方式安装Redis已经介绍了如何安装redis&#xff0c;在这篇文章中&#xff0c;将会教大家搭建Redis的几种高可用的架构&#xff1a;主从架构、哨兵集群、Cluster集群。 本篇文章使用的redis版本为6.2.13&#xff0c;不同版本的配置可能有略微的区别&a…

nodejS+vue网上招聘系统

求职者模块 系统的求职者模块可以分为 ①个人信息管理&#xff0c;可以更改个人用户名&#xff0c;密码等基本信息&#xff1b; ②岗位查询&#xff0c;可以根据岗位类型查询到该类型的岗位列表&#xff0c;并进行应聘申请。 ③应聘申请管理&#xff0c;可以查询到自己的应聘申…

数学建模:智能优化算法及其python实现

数学建模:智能优化算法及其python实现 智能优化算法简介差分进化算法(Differential Evolution,DE)遗传算法(Genetic Algorithm,GA)粒子群优化算法(Particle Swarm Optimization,PSO)模拟退火算法(Simulated Annealing,SA)蚁群算法(Ant Colony Optimization,ACO)…

HTTP代理SSL连接:保障网络安全的重要协议

HTTP代理SSL连接是一种网络安全协议&#xff0c;它结合了HTTP代理和SSL/TLS协议&#xff0c;用于在客户端和服务器之间建立加密通信通道。HTTP代理SSL连接可以保护数据在传输过程中不被窃听、篡改或伪造&#xff0c;从而确保数据的完整性、保密性和可靠性。在本文中&#xff0c…

目前很火的养猫微信小程序源码带流量主+搭建教程

目前很火的养猫微信小程序源码带流量主搭建教程。 搭建教程 进入小程序我们下载开发者工具 开发者工具安装好了 我们就把前端源码导入进开发者工具中 这里的APPID我们填写自己的小程序APPID 修改siteinfo.js里的uniacid和acid 这两个ID在刚才后端添加的小程序那里看 在把…

【前端打怪升级日志之微前端框架篇】微前端qiankun框架子应用间跳转方法

参考链接qiankun官网&#xff1a;微应用之间如何跳转&#xff1f; 1.主应用、子应用路由都是hash模式 主应用根据 hash 来判断微应用&#xff0c;无需考虑该问题 2.主应用根据path判断子应用 方法实现适用条件参数传递存在问题a标签跳转<a href"/toA"></…

新版WordPress系统文章自动采集插件/Auto Post pro完美运行版/多线程采集(wp自动采集)

源码介绍&#xff1a; 最新版WordPress系统文章自动采集插件&#xff0c;它是一款帮助用户提供方便快捷的文章自动采集方案的插件。WordPress自动采集插件&#xff0c;让内容采集变得高效便捷。作为Auto Post pro完美运行版&#xff0c;这里分享的是WordPress文章采集插件Auto…

TG Pro for Mac强大的硬件温度检测、风扇控制工具测评

无论您是旧机型还是全新MacBookPro&#xff0c;使用TG Pro均可延长Mac的使用寿命。小编就给大家详细说一下使用TG Pro的体验~ 打开TG Pro&#xff0c;您会注意到的第一件事是带有大量温度&#xff0c;风扇速度和诊断信息的主窗口。 这是您将与之交互的应用程序的主要区域之一。…

Selenium自动化测试 —— 通过cookie绕过验证码的操作!

验证码的处理 对于web应用&#xff0c;很多地方比如登录、发帖都需要输入验证码&#xff0c;类型也多种多样&#xff1b;登录/核心操作过程中&#xff0c;系统会产生随机的验证码图片&#xff0c;进行验证才能进行后续操作 解决验证码的方法如下&#xff1a; 1、开发做个万能…

js实现数组去重方式(12种方法)

目录 1、filter indexOf2、for object3、for includes4、for splice5、filter indexOf6、Map7、Set8、set Array.from9、sort 排序10、for findIndex11、双重for循环12、reduce 1、filter indexOf 数组去重&#xff1a;利用 filter 过滤 配合 indexOf 查找元素 var a…

Redis 是什么?

Redis是一种基于内存的数据库&#xff0c;数据的读写都是在内存中完成的&#xff0c;因此读写速度非常的快&#xff0c;常用于缓存&#xff0c;消息队列&#xff0c;分布式锁等场景。 Redis 在高并发项目中&#xff0c;担任着非常重要的作用&#xff0c;扛高并发的&#xff0c;…

docker+mysql+flask+redis+vue3+uwsgi+docker部署

首先拉取mysql的镜像&#xff0c;这里用的mysql5.7.6 docker pull mysql:5.7.6 镜像拉取完成后启动&#xff1a; docker run --name my-mysql -d -p 3306:3306 -v /usr/local/my-mysql/conf:/etc/mysql/conf.d -v /usr/local/my-mysql/data:/var/lib/mysql -e MYSQL_ROOT_PA…

layui子界面操作数据后主界面刷新怎么操作

项目场景&#xff1a; layui子界面进行了增删改查需要在关闭后让主界面刷新 解决方案&#xff1a; layui的admin.open方法支持传入回调函数,主要有以下几种回调: yes回调 用于确定/提交按钮点击后的回调参数: index,layero admin.open({ yes: function(index, layero){ /…

设计模式 - 代理模式

目录 一. 前言 二. 实现 三. 静态代理和动态代理 一. 前言 代理模式&#xff08;Proxy Pattern&#xff09;&#xff0c;为某个对象提供一种代理以控制对对象的访问。即客户端可通过代理对象间接访问目标对象&#xff0c;同时可限制、增强、修改目标对象的一些特性。访问者不…

vue3 - 按需导入使用Element Plus图标、iconify图标、本地SVG/PNG图标

GitHub Demo 地址 在线预览 vue3 - 按需导入使用Element Plus图标、iconify图标、本地SVG/PNG图标 [GitHub Demo 地址](https://github.com/iotjin/jh-vue3-admin)[在线预览 ](https://iotjin.github.io/jh-vue3-admin) 一、iconify插件安装使用效果图 二、通过自动导入使用ic…

如何利用React和Sass实现可定制的前端样式

如何利用React和Sass实现可定制的前端样式 引言&#xff1a; React是一种流行的JavaScript库&#xff0c;用于构建用户界面。它提供了组件化的方式来开发复杂的前端应用程序。而Sass是一种CSS预处理器&#xff0c;通过将CSS代码分解为模块&#xff0c;可以更方便地管理和组织样…

AIGC: 区块链与数据安全

随着国家将区块链纳入战略发展规划&#xff0c;数字经济蓬勃发展。近年来&#xff0c;数据的流通成为了实体经济赋能的关键&#xff0c;而在这一过程中&#xff0c;区块链技术和数据安全变得至关重要。 中国已经成为全球最大的数据体&#xff0c;每天产生大量数据。数字经济已…

软件测试人员必须知道的接口测试基础

一、首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能…

axios回调函数中this指向已经改变的解决方法

在axios回调函数中&#xff0c;this指向的是回调函数本身的作用域&#xff0c;而不是Vue实例的作用域。因此&#xff0c;你不能直接通过this访问Vue实例中的数据。为了解决这个问题&#xff0c;有几种方法&#xff1a; 1.使用箭头函数&#xff0c;箭头函数会绑定当前作用域的t…