2013-07-02 2 views
2

Я новичок в ИОС ..Как использовать CFStreams с помощью НОД

Я хочу подключиться к серверу, используя разъем подключения, я следовал учебник дал here

Это прекрасно работает, но я делал все в главном потоке пользовательского интерфейса, но представление зависало до тех пор, пока я не получил ответ от сервера ... Так что я немного искал 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 

на кнопке мыши я запустить таймер и вызвать подключения способ ..

метод
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];}); 

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

Если вы работаете его на отдельный поток, тогда вы должны позаботьтесь о Run Loop. Вы должны позвонить по телефону

[[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 дней им бороться с этой проблемой ... Пожалуйста, вы можете сделать мне еще одну услугу ... Мне нужно знать, как я могу отключить соединение после 30 секунд. – Audi

+0

Что вы подразумеваете под тайм-аутом здесь .... Вы имеете в виду, если сервер не отвечает, а затем истекает через 30 секунд? –

+0

Да ... если сервер не работает или есть какая-то проблема в сети ... – Audi

Смежные вопросы