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

382 阅读4分钟

文章来源:blog.csdn.net/cdy2143/art…

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

使用GCDAsyncSocket的方法如下:

1、github.com/robbiehanso…

\

2、使用代码

[plain]  view plain copy

  1. //建立连接  
  2. -(NSError *)setupConnection {  
  3.     if (nil == socket)  
  4.         socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];  
  5.     NSError *err = nil;  
  6.     NSLog(@"IP: %@, port:%i",hostAddress,hostPort);  
  7.     if (![socket connectToHost:hostAddress  onPort:hostPort error:&err]) {  
  8.         NSLog(@"Connection error : %@",err);  
  9.     } else {  
  10.         err = nil;  
  11.     }  
  12.     needConnect = YES;  
  13.     return err;  
  14. }  
  15.   
  16. //判断是否是连接的状态  
  17. -(BOOL)isConnected {  
  18.     return socket.isConnected;  
  19. }  
  20.   
  21. //断开连接  
  22. -(void)disConnect {  
  23.     needConnect = NO;  
  24.     [socket disconnect];  
  25. }  
  26.   
  27. //取得连接  
  28. -(void)getConnection {  
  29.     if (![socket isConnected]) {  
  30.         [self disConnect];  
  31.         //        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(setupConnection) userInfo:nil repeats:NO];  
  32.         //        NSLog(@"scheduled start");  
  33.         [self setupConnection];  
  34.     }  
  35. }  
  36.   
  37. -(void)sendCMD {  
  38.     [self getConnection];  
  39. //    NSString* cmd = [[NSString alloc] init];  
  40. //    cmd = [cmd stringByAppendingString:@"BBBB1,zzc,202cb962ac59075b964b07152d234b70,201304182033EEEE"];  
  41.     NSString* cmd = @"BBBB1,zzc,202cb962ac59075b964b07152d234b70,201304182033EEEE\n";  
  42.     NSData *data = [cmd dataUsingEncoding:NSUTF8StringEncoding];  
  43.     [socket writeData:data withTimeout:20 tag:1];  
  44. }  
  45.   
  46. //socket连接成功后的回调代理  
  47. -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {  
  48.     NSLog(@"onSocket:%p didConnectToHost:%@ port:%hu", sock, host, port);  
  49.     [delegate networkConnected];  
  50.     [self listenData];  
  51. }  
  52.   
  53. //socket连接断开后的回调代理  
  54. -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {  
  55.     NSLog(@"DisConnetion");  
  56.     [socket disconnect];  
  57.     [delegate networkDisconnect];  
  58.     //    if (needConnect)  
  59.     //        [self getConnection];  
  60. }  
  61.   
  62. //读到数据后的回调代理  
  63. -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {  
  64.     NSLog(@"receive datas from method 1");  
  65.     //    NSLog(@"Data length = %d",[data length]);  
  66.     [self listenData];  
  67.     [delegate readData:data];  
  68. //    [self splitData:data];  
  69.     //    [self listenData];  
  70. }  
  71.   
  72. -(void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {  
  73.      NSLog(@"Reading data length of %d",partialLength);  
  74. }  
  75.   
  76. //发起一个读取的请求,当收到数据时后面的didReadData才能被回调  
  77. -(void)listenData {  
  78. //    NSString* sp = @"\n";  
  79. //    NSData* sp_data = [sp dataUsingEncoding:NSUTF8StringEncoding];  
  80.     [socket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:1];  
  81. //    [socket readDataWithTimeout:-1 tag:1];  
  82. }  


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

[plain]  view plain copy

  1. <p class="p1">NSMutableData<span style="font-family: Arial, Helvetica, sans-serif;">* restData;</span></p>//分割数据包  
  2. -(void)splitData:(NSData*)orignal_data {  
  3.     NSUInteger l = [orignal_data length];  
  4.     NSLog(@"Data length1 = %d",l);  
  5.     NSString* sp = @"\n";  
  6.     NSData* sp_data = [sp dataUsingEncoding:NSUTF8StringEncoding];  
  7.     NSUInteger sp_length = [sp_data length];  
  8.     NSUInteger offset = 0;  
  9.     int line = 0;  
  10.     while (TRUE) {  
  11.         NSUInteger index = [self indexOfData:sp_data inData:orignal_data offset:offset];  
  12.         if (NSNotFound == index) {  
  13.             if (offset<l) {  
  14.                 NSLog(@"Have data not read");  
  15.                 NSRange range = {offset,l-offset};  
  16.                 NSData* rest = [orignal_data subdataWithRange:range];  
  17.                 if (restData == nil) {  
  18.                     restData = [[NSMutableData alloc] init];  
  19.                 }  
  20.                 [restData appendData:rest];  
  21.             }  
  22.             return;  
  23.         }  
  24.         NSUInteger length = index + sp_length;  
  25.         NSRange range = {offset,length-offset};  
  26.         NSData* sub = [orignal_data subdataWithRange:range];  
  27.         if (restData != nil) {  
  28.             [restData appendData:sub];  
  29.             [delegate readData:restData];  
  30.             restData = nil;  
  31.         } else {  
  32.             NSLog(@"line %d",line++);  
  33.             [delegate readData:sub];  
  34.         }  
  35.         offset += length;  
  36.     }  
  37. }  
  38.   
  39. //查找指定的数据包的位置  
  40. - (NSUInteger)indexOfData:(NSData*)needle inData:(NSData*)haystack offset:(NSUInteger)offset  
  41. {  
  42.     Byte* needleBytes = (Byte*)[needle bytes];  
  43.     Byte* haystackBytes = (Byte*)[haystack bytes];  
  44.       
  45.     // walk the length of the buffer, looking for a byte that matches the start  
  46.     // of the pattern; we can skip (|needle|-1) bytes at the end, since we can't  
  47.     // have a match that's shorter than needle itself  
  48.     for (NSUInteger i=offset; i < [haystack length]-[needle length]+1; i++)  
  49.     {  
  50.         // walk needle's bytes while they still match the bytes of haystack  
  51.         // starting at i; if we walk off the end of needle, we found a match  
  52.         NSUInteger j=0;  
  53.         while (j < [needle length] && needleBytes[j] == haystackBytes[i+j])  
  54.         {  
  55.             j++;  
  56.         }  
  57.         if (j == [needle length])  
  58.         {  
  59.             return i;  
  60.         }  
  61.     }  
  62.     return NSNotFound;  
  63. }  

\