即时通讯1- 用GCDAsyncSocket解决读取数据丢失

原文地址:http://blog.csdn.net/cdy2143/article/details/8963422


在项目中,一直都是用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、附上从网络上取得到数据包后,自己用分割符来分割数据,如用换行符号分割数据包

 

 

[plain] view plaincopy
 
<p class="p1">NSMutableData<span style="font-family: Arial, Helvetica, sans-serif;">* restData;</span></p>//分割数据包  -(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;  
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值