美文网首页程序员iOS DeveloperiOS学习笔记
IOS-群聊天服务端以及客户端的心跳包(三)

IOS-群聊天服务端以及客户端的心跳包(三)

作者: 温学振 | 来源:发表于2018-03-07 10:50 被阅读159次

    群聊思路:客户端ABC都连接到服务器,当客户端A发送信息给服务器,服务端把A的信息发送给除A以外的B、C客户端

    在这的基础上IOS-基于CocoaAsyncSocket的服务端的监听(二)
    服务器方面:唯一变化的就是在服务端读取客户端请求数据的时候要做判断

    #pragma mark 服务端读取客户端请求数据
    - (void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag{
        NSLog(@"clientSocket读取保存在severSocket的clientSocket数据:%@",clientSocket);
        
        //1、NSData转成string
        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      
        //2、群聊服务:把当前客户端的数据转发给其他客户端,ABC客户端都连接了服务端,A客户端发送消息给服务端,服务端要遍历存在服务端的客户端数据,把除了A客户端发送的消息转发给BC。这样可以构成一个群聊的服务
        NSLog(@"接受到客户端上传的数据responseStr:%@",str);
        //3、处理请求,返回数据给客户端
        for (GCDAsyncSocket *socket in self.clientSockets) {
            if (socket == clientSocket) {
                //是自己A 不发送
            }else{
                //是BC 把存在服务端的A消息发送给BC
                [socket writeData:data withTimeout:-1 tag:0];
    
            }
        }
    #warning 只会读取1次 每次读完数据都要监听
        [clientSocket readDataWithTimeout:-1 tag:0];
    }
    

    客户端方面
    1、实现socket以及发送消息

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //实现聊天室雏形
        //1.连接到群聊服务器
        //1.1.创建客户端socket对象
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
        //1.2.发送连接请求
        NSError *error;
        [self.clientSocket connectToHost:@"192.168.1.75" onPort:5288 error:&error];
        if (!error) {
            NSLog(@"%@",error);
        }
    }
    

    2、socket代理判断是否连接成功

    #pragma mark socket连接成功
    - (void)socket:(GCDAsyncSocket *)clientSocket didConnectToHost:(NSString *)host port:(uint16_t)port{
        NSLog(@"与服务器连接成功");
        //客户端监听读取数据
        [clientSocket readDataWithTimeout:-1 tag:0];
    }
    #pragma mark socket连接失败
    - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
        NSLog(@"与服务器断开连接%@",err);
    
        self.clientSocket = nil;
        self.clientSocket.delegate = nil;
    }
    

    3、读取服务端返回的数据

    #pragma mark 读取消息,socket客户端监听数据
    - (void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag{
        NSLog(@"读取消息");
        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@读取消息",str);
        /*添加消息
        if (str) {
            [self.dataSource addObject:str];
    #warning 要在主线程
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [self.tableView reloadData];
            }];
        }*/
    #warning 读完数据继续监听。// withTimeout -1 : 无穷大,一直等
        [clientSocket readDataWithTimeout:-1 tag:0];
    }
    

    4、创建一个Btn手动发送消息

    #pragma mark 手动发送
    - (IBAction)send:(id)sender {
        NSString *str = @"11";
        if (str.length ==0 ) {//无数据
            return;
        }
     /*   [self.dataSource addObject:str];
    //    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self.tableView reloadData];
    //    }];*/
        //发送数据
        [self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }
    

    当然也可以定时发送,就是所谓的心跳包,每次间隔几秒给服务器发送一条双方协商好的固定格式,如果粘包,那就在固定格式末尾加上某个特定符号,让服务端监听特定符号是否接受成功。因为在某些特殊情况下,包的发送数据过大可能会发n次。

    #pragma mark 心跳发送
    // 添加定时器
    - (void)addTimer
    {
        // 长连接定时器
        self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
        // 把定时器添加到当前运行循环,并且调为通用模式
        [[NSRunLoop currentRunLoop] addTimer:self.connectTimer forMode:NSRunLoopCommonModes];
    }
    // 心跳连接
    - (void)longConnectToSocket
    {
        // 发送固定格式的数据,指令@"longConnect",这里要和服务器有固定的格式
        float version = [[UIDevice currentDevice] systemVersion].floatValue;
        NSString *longConnect = [NSString stringWithFormat:@"ping%f",version];
        
        NSData  *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
        
        //发送心跳包
        [self.clientSocket writeData:data withTimeout:- 1 tag:0];
    }
    

    相关文章

      网友评论

        本文标题:IOS-群聊天服务端以及客户端的心跳包(三)

        本文链接:https://www.haomeiwen.com/subject/ntilfftx.html