如果处理服务器与客户端时间不一致的问题

  1. 前一段时间做了一个倒计时的功能,要求每个tableViewcell里面都嵌入倒计时的功能。我也封装了一个工具类,详细请看这里
  2. 但是倒计时如果不是用服务器的现在时间进行剩余时间计算的话,就可能出现bug(比如一个商品,倒计时1小时停售,服务器已经过了这停售时间,从而停售了,但是客户端的时间比服务器时间向后调了1小时,那么客户端就会以为还没有停售)
  3. 这就要求要用客户端的时间求出服务器的时间

1、大体思路

其实很简单就说一下大体的思路,在附一个小的工具类,很简单。。。
1. 封装一个类,在请求到后台的时间戳后,把本地时间与后台时间戳进行对比,记录时间差,最后每次时间计算的时候,都可以用本地时间求出服务器的时间。
2. 关键是什么时候请求服务器时间。
1.我们先分析一下,首先,这种时间差,越早知道越好,所以,在app启动的时候就要请求服务器时间,并计算差值。

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
    app刚刚启动的时候创建并给出serverTime,内部计算了服务器时间

2.假设,用户很调皮,在app运行后,就退出去,对手机的时间设置成一个随意时间。那再进来,再用以前储存的时间差计算服务器时间,岂不是炸了。
所以在app进入后台、应用程序编程不激活状态、从后台进入到前台等都要调用一下,一下代码满足了这些时机的需求

-(void)applicationWillResignActive:(UIApplication *)application {}
    应用程序变成不激活状态,双击home建,应用程序不在相应用户点击的时候
-(void)applicationDidEnterBackground:(UIApplication *)application{}
    应用程序进入到后台的时候调用,双击home建不会调用
-(void)applicationWillEnterForeground:(UIApplication *)application{}
    应用程序从后台进入到前台以后调用这个方法, 应用启动不会调用
-(void)applicationDidBecomeActive:(UIApplication *)application{}
    应用程序变为激活状态的时候会调用这个方法,(用户可以进行用户交互的时候调用)
-(void)applicationWillTerminate:(UIApplication *)application{}
    系统将要推出(终止)的时候调用

2. 代码剪辑
.h

#import <Foundation/Foundation.h>
@interface PYServerAndClientTime : NSObject
///单利
+ (instancetype) sharedServerAndClientTime;
///内部创建了sharedServerAndClientTime对象
+ (instancetype) serVerAndClientTimeWithServerTime: (NSString *)serverTime;
///服务器的时间戳
@property (nonatomic,copy) NSString *serverTime;
///计算后的服务器时间
@property (nonatomic,strong,readonly) NSDate *serverAndClientDate;
///计算后服务器时间的timeInterval
@property (nonatomic,assign,readonly) NSNumber *serverAndClientTimeInterval;
///服务器与客户端时间的时间差
@property (nonatomic,assign,readonly) NSNumber *timeDifference;
@end

.m

@implementation PYServerAndClientTime
+ (instancetype) sharedServerAndClientTime {
    static dispatch_once_t onceToken;
    static PYServerAndClientTime *_instance;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc]init];
    });
    return _instance;
}


+(instancetype) serVerAndClientTimeWithServerTime: (NSString *)serverTime {
    PYServerAndClientTime *serverAndClientTime = [PYServerAndClientTime sharedServerAndClientTime];
    serverAndClientTime.serverTime = serverTime;
    return serverAndClientTime;
}
//MARK: setter
-(void)setServerTime:(NSString *)serverTime {
    _serverTime = serverTime;
   double serverTimeDouble = serverTime.longLongValue;
    //计算当前的时间秒数
    NSTimeInterval currentDateInterval = [[[NSDate alloc]init] timeIntervalSince1970];
    //计算时差
     NSNumber *timeDifferenceTemp = @(serverTimeDouble - currentDateInterval);
    [self setValue:timeDifferenceTemp forKey:@"timeDifference"];
}
//MARK: getter
-(NSDate *)serverAndClientDate {
    return [NSDate dateWithTimeIntervalSinceNow:self.timeDifference.doubleValue];;
}
-(NSNumber *)serverAndClientTimeInterval {
    return @([self.serverAndClientDate timeIntervalSince1970]);
}
@end

appDelegate

#import "AppDelegate.h"
#import "PYServerAndClientTime.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
//根据服务器时间计算与本地时间的时间差
-(void)serverAndClientTime {
    /**......
     服务器请求数据
     .......
     */
    NSString *serverTime;//服务器求情下来之后的服务器时间戳
    PYServerAndClientTime *serverAndClientTime = [PYServerAndClientTime sharedServerAndClientTime];
    serverAndClientTime.serverTime = serverTime;
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //app刚刚启动的时候创建并给出serverTime,内部计算了服务器时间
    [self serverAndClientTime];
    return YES;
}
-(void)applicationWillResignActive:(UIApplication *)application {
    // 应用程序变成不激活状态,双击home建,应用程序不在相应用户点击的时候
    [self serverAndClientTime];
}
-(void)applicationDidEnterBackground:(UIApplication *)application {
    //应用程序进入到后台的时候调用,双击home建不会调用
  [self serverAndClientTime];
}

-(void)applicationWillEnterForeground:(UIApplication *)application {
    //应用程序从后台进入到前台以后调用这个方法, 应用启动不会调用
  [self serverAndClientTime];
}
-(void)applicationDidBecomeActive:(UIApplication *)application {
    //应用程序变为激活状态的时候会调用这个方法,(用户可以进行用户交互的时候调用)
   [self serverAndClientTime];
}
-(void)applicationWillTerminate:(UIApplication *)application {
   //系统将要推出(终止)的时候调用
}
@end
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于后台客户端频繁与 MQTT 服务器断连重连的问题,可能有几种原因导致。我会给出一些常见的解决方案,希望能对您有所帮助。 1. 检查网络连接:首先确保客户端与 MQTT 服务器之间的网络连接是稳定的,可以通过 ping 命令或其他网络测试工具来验证。 2. 处理心跳信号:MQTT 协议中有心跳机制,客户端需要定期发送心跳信号以维持与服务器的连接。您可以检查客户端是否正确实现了心跳机制,并且心跳间隔设置合理。 3. 优化重连策略:如果客户端服务器的连接断开,您可以考虑优化重连策略。例如,可以使用指数退避算法来逐渐增加重连间隔时间,避免频繁重连对服务器造成压力。 4. 检查服务器配置:确保 MQTT 服务器的配置参数正确设置,包括最大连接数、最大消息数量等。如果超过了服务器的负载能力,可能会导致频繁的断连重连。 5. 处理异常情况:在客户端代码中处理异常情况是很重要的。例如,如果网络连接异常断开,可以尝试重新连接;如果连接失败多次仍无法建立连接,可以考虑进行错误处理或报警。 6. 使用保持持久连接的策略:保持持久连接是一种可行的解决方案。通过使用一个长时间持续的连接,可以避免频繁的连接和断开操作。 希望以上解决方案能解决您遇到的问题。如果仍然存在问题,请提供更多的细节和错误日志,我将尽力帮助您解决。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值