2013-07-02 62 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