用GCDAsyncSocket解决AsyncSocket读取数据时丢失部分消息

在项目中,一直都是用AsyncSocket的开源项目来做IOS的Socket的开发,现在遇到一个问题:当数据包比较频繁的发送到手机时,即使使用了readDataToData,还是会出现丢包的问题且读到的包中还会出现分割符。后面终于参考了其他的文章,看到GCDAsyncSocket,结果试了一把,readDataToData,能正常分割数据,即按行来分,且不丢包了。

使用GCDAsyncSocket的方法如下:

1、https://github.com/robbiehanson/CocoaAsyncSocket,从这个地址,将GCD目录下的GCDAsyncSocket.h和GCDAsyncSocket.m文件下载下来,添加到你的项目中,然后,在引入CFNetwork.framework和Security.framework,如下图:


2、使用代码

//建立连接
-(NSError *)setupConnection {
    if (nil == socket)
        socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    NSError *err = nil;
    NSLog(@"IP: %@, port:%i",hostAddress,hostPort);
    if (![socket connectToHost:hostAddress  onPort:hostPort error:&err]) {
        NSLog(@"Connection error : %@",err);
    } else {
        err = nil;
    }
    needConnect = YES;
    return err;
}

//判断是否是连接的状态
-(BOOL)isConnected {
    return socket.isConnected;
}

//断开连接
-(void)disConnect {
    needConnect = NO;
    [socket disconnect];
}

//取得连接
-(void)getConnection {
    if (![socket isConnected]) {
        [self disConnect];
        //        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(setupConnection) userInfo:nil repeats:NO];
        //        NSLog(@"scheduled start");
        [self setupConnection];
    }
}

-(void)sendCMD {
    [self getConnection];
//    NSString* cmd = [[NSString alloc] init];
//    cmd = [cmd stringByAppendingString:@"BBBB1,zzc,202cb962ac59075b964b07152d234b70,201304182033EEEE"];
    NSString* cmd = @"BBBB1,zzc,202cb962ac59075b964b07152d234b70,201304182033EEEE\n";
    NSData *data = [cmd dataUsingEncoding:NSUTF8StringEncoding];
    [socket writeData:data withTimeout:20 tag:1];
}

//socket连接成功后的回调代理
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"onSocket:%p didConnectToHost:%@ port:%hu", sock, host, port);
    [delegate networkConnected];
    [self listenData];
}

//socket连接断开后的回调代理
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
    NSLog(@"DisConnetion");
    [socket disconnect];
    [delegate networkDisconnect];
    //    if (needConnect)
    //        [self getConnection];
}

//读到数据后的回调代理
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSLog(@"receive datas from method 1");
    //    NSLog(@"Data length = %d",[data length]);
    [self listenData];
    [delegate readData:data];
//    [self splitData:data];
    //    [self listenData];
}

-(void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {
     NSLog(@"Reading data length of %d",partialLength);
}

//发起一个读取的请求,当收到数据时后面的didReadData才能被回调
-(void)listenData {
//    NSString* sp = @"\n";
//    NSData* sp_data = [sp dataUsingEncoding:NSUTF8StringEncoding];
    [socket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:1];
//    [socket readDataWithTimeout:-1 tag:1];
}

3、付上从网络上取得到数据包后,自己用分割符来分割数据,如用换行符号分割数据包

NSMutableData* restData;

//分割数据包 -(void)splitData:(NSData*)orignal_data { NSUInteger l = [orignal_data length]; NSLog(@"Data length1 = %d",l); NSString* sp = @"\n"; NSData* sp_data = [sp dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger sp_length = [sp_data length]; NSUInteger offset = 0; int line = 0; while (TRUE) { NSUInteger index = [self indexOfData:sp_data inData:orignal_data offset:offset]; if (NSNotFound == index) { if (offset<l) { NSLog(@"Have data not read"); NSRange range = {offset,l-offset}; NSData* rest = [orignal_data subdataWithRange:range]; if (restData == nil) { restData = [[NSMutableData alloc] init]; } [restData appendData:rest]; } return; } NSUInteger length = index + sp_length; NSRange range = {offset,length-offset}; NSData* sub = [orignal_data subdataWithRange:range]; if (restData != nil) { [restData appendData:sub]; [delegate readData:restData]; restData = nil; } else { NSLog(@"line %d",line++); [delegate readData:sub]; } offset += length; } } //查找指定的数据包的位置 - (NSUInteger)indexOfData:(NSData*)needle inData:(NSData*)haystack offset:(NSUInteger)offset { Byte* needleBytes = (Byte*)[needle bytes]; Byte* haystackBytes = (Byte*)[haystack bytes]; // walk the length of the buffer, looking for a byte that matches the start // of the pattern; we can skip (|needle|-1) bytes at the end, since we can't // have a match that's shorter than needle itself for (NSUInteger i=offset; i < [haystack length]-[needle length]+1; i++) { // walk needle's bytes while they still match the bytes of haystack // starting at i; if we walk off the end of needle, we found a match NSUInteger j=0; while (j < [needle length] && needleBytes[j] == haystackBytes[i+j]) { j++; } if (j == [needle length]) { return i; } } return NSNotFound; }


评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值