用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 itselffor (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 matchNSUInteger j=0;while (j < [needle length] && needleBytes[j] == haystackBytes[i+j]){j++;}if (j == [needle length]){return i;}}return NSNotFound;}

看自家总在期待,不知将来好歹,新乐吧总在不断等待,

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

相关文章:

你感兴趣的文章:

标签云: