GCDAsyncSocket不能读取数据的原因

按照网上找到的例子,尝试做简单的TCP发送和接收。

结果发现事实并不是那么回事,为什么?到stack overflow里看到一个原因说有可能delegate被系统自动释放掉,这样就不会有delegate。但是没有看到好的例子。

一般的例子就是在view controller里面引入GCDAsyncSocket.h然后开始初始化,然后就在view controller里面实现GCDAsyncSocketDelegate,然后就可以在view did load里面做初始化和调用连接,读取和写入这些。然后如果完成到相应的步骤,会有相应的delegate被呼叫。

不过,其实这样是不行的,只能写出去,但读取的delegate不会被执行。原因可能是view controller这个类本身在做完view did load之后就被系统自动释放了,然后socket的didReadData就为空,就不会被调用。

具体是不是这个原因我也不是很清楚,就是跟iOS系统的ARC机制有关,也跟GCD有关。这些概念我其实还不是很清楚。

总之我知道这是跟内存管理和进程调度有关。

如果不使用GCDAsyncSocket而采用旧的AsyncSocket则没有这种问题,能正常调用读写的delegate。所以感觉还简单一点。搞不懂为什么非要用GCD这种看起来高级,实际上很坑爹的方式。

不过我还是找到办法既可以用GCD,又可以让read的delegate执行的方法。稍微麻烦一点,就是自己定义一个class,在这个class里定义socket和实现相关的delegate,要注意的是这个class要提供一个share方法,里面会定义一个static的这个对象本身,这样就保证以后都一直能引用得到,而不会被系统自动释放掉。

+(TcpManager *)Share
{
    static TcpManager *manager=nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        manager=[[TcpManager alloc]init];
        manager.asyncsocket=[[GCDAsyncSocket alloc]initWithDelegate:manager delegateQueue:dispatch_get_main_queue()];
        
    });
    return manager;
}

这样在view controller里需要用tcp时

TcpManager *tcp = [TcpManager Share];
    GCDAsyncSocket *socket = tcp.asyncsocket;
    if (![socket connectToHost:@"192.168.1.212" onPort:5000 error:&err]) {
        NSLog(@"fail to connect");
    }
    
    [socket readDataWithTimeout:3 tag:1];
    [socket writeData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

用这种方式来调用就可以了。

完整的代码:

#import "ViewController.h"
#import "TcpManager.h"

@interface ViewController ()

@end

@implementation ViewController


- (void)viewDidLoad {
    NSError *err = nil;
    
    [super viewDidLoad];
    NSLog(@"we are going to test tcp");

    TcpManager *tcp = [TcpManager Share];
    GCDAsyncSocket *socket = tcp.asyncsocket;
    if (![socket connectToHost:@"192.168.1.212" onPort:5000 error:&err]) {
        NSLog(@"fail to connect");
    }
    
    [socket readDataWithTimeout:3 tag:1];
    [socket writeData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
    
}

@end


tcp manager的代码:
#import "TcpManager.h"
@interface TcpManager() <GCDAsyncSocketDelegate>

@end

@implementation TcpManager
+(TcpManager *)Share
{
    static TcpManager *manager=nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        manager=[[TcpManager alloc]init];
        manager.asyncsocket=[[GCDAsyncSocket alloc]initWithDelegate:manager delegateQueue:dispatch_get_main_queue()];
        
    });
    return manager;
}

-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    NSLog(@"didConnectToHost %@ port %d",host,port);
}


-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"disconnected");
}


-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    
    NSLog(@"didReadData read data");
    NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"message is: \n%@",message);
    
//    [sock disconnect];
}


-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    //    [sock disconnect];
    NSLog(@"didWriteDataWithTag");
}


-(NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length
{
    NSLog(@"timeout");
    
    return 0;
}

-(BOOL)destroy
{
    
    [_asyncsocket disconnect];
    return YES;
}

@end

头文件:

#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"
//#import "AsyncSocket.h"
@interface TcpManager : NSObject
@property(strong,nonatomic) GCDAsyncSocket *asyncsocket;

+(TcpManager *)Share;
-(BOOL)destroy;
@end

其它的就不贴了。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值