2013-07-02 31 views
2

我是新手到iOS使用CFStreams ..如何使用GCD

我想用插座连接连接到一台服务器,我也跟着给 here

这工作得很好的教程,但我在主UI线程中做了所有事情,但视图被冻结,直到我得到服务器的响应...所以我GOOGLE了一下,发现了GCD在ios中的概念...所以在我的按钮上点击我呼叫以下代码...

[SVProgressHUD showWithStatus:@"Processing.."]; 
    [self.view setUserInteractionEnabled:NO]; 


    qt = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(qt, ^{ 
CFReadStreamRef readStream; 
CFWriteStreamRef writeStream; 
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip, 54000, &readStream, &writeStream); 

inputStream = (NSInputStream *)readStream; 
outputStream = (NSOutputStream *)writeStream; 
[inputStream setDelegate:self]; 
[outputStream setDelegate:self]; 

[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

[inputStream open]; 
[outputStream open]; 

NSData *data = [[NSData alloc] initWithData:[pinno dataUsingEncoding:NSASCIIStringEncoding]]; 
[outputStream write:[data bytes] maxLength:[data length]]; 
[outputStream close]; 
    }); 

而且我处理使用功能

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 

    NSLog(@"StreamEvent %i",streamEvent); 
    switch (streamEvent) { 

          dispatch_async(dispatch_get_main_queue(), ^{[SVProgressHUD dismiss]; 
      }); 

     case NSStreamEventOpenCompleted: 
      NSLog(@"Stream opened"); 
      break; 

     case NSStreamEventHasBytesAvailable: 
       NSLog(@"Stream has byte Avaliable"); 

      if (theStream==inputStream) { 

       while ([inputStream hasBytesAvailable]) { 
        uint8_t buffer[1024]; 
        int len; 
        len = [inputStream read:buffer maxLength:sizeof(buffer)]; 
        if(len>0){ 
         NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; 
         [self.view setUserInteractionEnabled:YES]; 

         NSLog(@"output %@",output); 


        } 
       } 
      } 
      break; 

     case NSStreamEventErrorOccurred: 
      [self.view setUserInteractionEnabled:YES]; 

      NSLog(@"Can not connect to the host!"); 
      break; 

     case NSStreamEventEndEncountered: 
      [self.view setUserInteractionEnabled:YES]; 

      break; 

     default: 
      [self.view setUserInteractionEnabled:YES]; 

      NSLog(@"Unknown event"); 

    } 
} 

使用上面的代码中,我得到的服务器和服务器还发送成功响应的请求事件,但我没有收到在处理事件的方法的任何数据,但我没有得到一个hasbytesavaliable事件..我的控制台日志

2013-07-02 14:06:15.312 Multi[899:1c03] StreamEvent 1 
2013-07-02 14:06:15.313 Multi[899:1c03] Stream opened 
2013-07-02 14:06:15.313 Multi[899:1c03] StreamEvent 4 
2013-07-02 14:06:15.313 Multi[899:1c03] Unknown event 

任何想法,我做错了......

Edit:Updated Code 

在按钮点击我开始计时,并调用connect方法..

counter=[NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(stream:handleEvent:) userInfo:nil repeats:NO]; 


     qt = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
     dispatch_async(qt, ^{[self connect];}); 

连接方法:

CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip, 54000, &readStream, &writeStream); 


    inputStream = (NSInputStream *)readStream; 
    outputStream = (NSOutputStream *)writeStream; 

    NSRunLoop *loop = [NSRunLoop currentRunLoop]; 

    [inputStream setDelegate:self]; 
    [outputStream setDelegate:self]; 

    [inputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode]; 
    [outputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode]; 

    [inputStream open]; 
    [outputStream open]; 

    NSData *data = [[NSData alloc] initWithData:[pinno dataUsingEncoding:NSASCIIStringEncoding]]; 
    [outputStream write:[data bytes] maxLength:[data length]]; 
    [outputStream close]; 

    [loop run]; 

流处理事件的

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 
    Username.text = @""; 
    Password.text = @""; 
    [self disconnect]; 
    if (counter!=nil){ 
     [counter invalidate]; 
     counter=nil; 
    } 

    NSLog(@"StreamEvent %i",streamEvent); 
    switch (streamEvent) { 

     case NSStreamEventOpenCompleted: 
      NSLog(@"Stream opened"); 
      break; 

     case NSStreamEventHasBytesAvailable: 
      if (theStream==inputStream) { 

       while ([inputStream hasBytesAvailable]) { 
        uint8_t buffer[1024]; 
        int len; 
        len = [inputStream read:buffer maxLength:sizeof(buffer)]; 
        if(len>0){ 
         NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; 

         NSLog(@"output %@",output); 
         [SVProgressHUD dismiss]; 
         main = [[Mainmenu alloc] 
           initWithNibName:@"Mainmenu" 
           bundle:nil]; 
         //      [self.view addSubview:main.view]; 
         [self presentViewController:main animated:NO completion:NO]; 
        } 
       } 
      } 
      dispatch_async(dispatch_get_main_queue(), ^{[SVProgressHUD dismiss]; 
      }); 

      break; 

     case NSStreamEventErrorOccurred: 

      NSLog(@"Can not connect to the host!"); 
      dispatch_async(dispatch_get_main_queue(), ^{[self dismiss:@"Cannot connect to host!"]; 
      }); 

      break; 

     case NSStreamEventEndEncountered: 
      dispatch_async(dispatch_get_main_queue(), ^{[self dismiss:@"Connection Error"]; 
      }); 

      break; 

     default: 
      NSLog(@"Unknown event"); 
      dispatch_async(dispatch_get_main_queue(), ^{[self dismiss:@"Timeout Expired"]; 
      }); 

    } 
} 

和断开连接的方法..

-(void) disconnect 
{ 
    [inputStream close]; 
    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [outputStream close]; 
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [inputStream setDelegate:nil]; 
    inputStream = nil; 
    [outputStream setDelegate:nil]; 
    outputStream = nil; 

} 

回答

3

如果你运行它一个单独的线程,然后你必须照顾运行循环。您必须致电

[[NSRunLoop currentRunLoop] run];

在正确的时间。

如下更改代码的这一部分,也将努力肯定的:

inputStream = (NSInputStream *)readStream; 
outputStream = (NSOutputStream *)writeStream; 

NSRunLoop *loop = [NSRunLoop currentRunLoop]; 

[inputStream setDelegate:self]; 
[outputStream setDelegate:self]; 

[inputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode]; 
[outputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode]; 

[inputStream open]; 
[outputStream open]; 

[loop run]; 
+0

万分感谢的人... 2天的IM这个问题苦苦挣扎......可以请你帮我一个忙...我需要知道如何在30秒后超时连接.. – Audi

+0

这是什么意思在这里暂停....你的意思是如果服务器没有响应,然后在30秒后超时? –

+0

是的......如果服务器停机或者网络中有问题... – Audi