2011-10-03 6 views
1

내 프로그램에서 나는 runloop에서 예약 된 읽기 및 쓰기 스트림을 가지고 있으며 정상적으로 작동합니다. 나중에 프로그램에서 읽기 또는 쓰기로 다른 스트림을 열고 싶은데 역할에 따라 다르지만 같은 서버로 동일한 runloop로 예약하려고하지만 작동하지 않습니다. 새로 만든 스트림에서 open을 호출했지만 새로 열어 본 스트림에 NSStreamEventOpenCompleted 이벤트가 표시되지 않습니다. 내가 스트림 및 이벤트 처리하는 대리자의 구현을 만드는 방법은 다음과 같습니다iOS의 동일한 런 루프에서 여러 소켓 스트림을 여는 방법은 무엇입니까?

controller.m을

- (void)initNetworkCommunication:(NSString *)ip_address withPort:(NSInteger)port role:(network_role_t)role 
{ 
    CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 

    NSLog(@"server IP: %@, port: %d, role: %d", ip_address, port, role); 
    if (port != 8080) { 
     if (role == HOST) { 
      CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip_address, port, NULL, &writeStream); 
      imageOutStream = (NSOutputStream *)writeStream; 
      [imageOutStream setDelegate:self]; 
      [imageOutStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
      [imageOutStream open]; 
      NSLog(@"host connected"); 
     } else if (role == CLIENT) { 
      CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip_address, port, &readStream, NULL); 
      imageInStream = (NSInputStream *)readStream; 
      [imageInStream setDelegate:self]; 
      [imageInStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
      [imageInStream open]; 
      NSLog(@"client connected"); 
     } 
    } else { 
     CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip_address, port, &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]; 
    } 
} 

위임 구현 :

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

    switch (streamEvent) { 
     case NSStreamEventHasBytesAvailable: 
      if (theStream == inputStream) { 
       /* send regular data */ 
      } else if (theStream == imageInStream) { 
       /* send raw data */ 
      } 
     break; 
     case NSStreamEventOpenCompleted: 
      if (theStream == imageOutStream) { 
       NSLog(@"imageOutStream opened"); 
      } else if (theStream == imageInStream) { 
       NSLog(@"imageInStream opened"); 
      } 
     break; 
     case NSStreamEventErrorOccurred: 
      //NSError *theError = [theStream streamError]; 
      NSLog(@"Socket error string: %@", [[theStream streamError] localizedDescription]); 
     break; 
    } 
} 

그래서 내가 imageOutStream가 열리고하지 않고 imageInStream은 서버에 연결될 때 인쇄됩니다. 내가 알게 된 것은 scheduleInRunLoop에 있습니다 : currentRunLoop 대신 mainRunLoop을 사용하면 imageInStream 및 imageOutStream에 대해 스트림을 볼 수 있지만 출력을 열어 볼 수는 있지만 송신과 수신에는 여전히 문제가 있습니다. 스트림을 예약하는 데 문제가 있습니까? 또는 여러 소켓 스트림을 만들려면 scheduleInRunLoop 이외의 다른 메서드를 사용해야합니다. 도와 주셔서 감사합니다.

답변

0

먼저, -stream : handleEvent : : NSLog(@"stream %@ got event %x", theStream, (unsigned)streamEvent);과 같은 맨 위에 무조건적인 로깅을 추가합니다. 이것은 당신이 당신이 (어떤 종류의) 것으로 의심되는 당신이 다루지 않는 사건이 일어나고 있는지를 알려줄 것입니다. NSStream docs에서

,

스트림 이벤트 상수

하나 이러한 상수의 이상이 스트림의 두 번째 매개 변수에서 비트 필드로 대리인에게 전송 될 수 있습니다 :의 handleEvent :.

비트 필드 인 경우 쉽게 전환 할 수 없습니다. 스트림이 개를 열었 음을 의미하는 3 (NSStreamEventOpenCompleted|NSStreamEventHasBytesAvailable) 일 수 있습니다. 데이터를 읽을 수 있습니다.

쉬운 수정 응답이

if (streamEvent&NSStreamEventOpenCompleted) { 
    ... 
} 

if (streamEvent&NSStreamEventHasBytesAvailable) { 
    ... 
} 

... 
+0

덕분에 같이 보입니다. 다른 스레드에서 initNetworkCommunication을 호출했기 때문에 스레드의 runloop을 사용하고있었습니다. 나는 mainRunLoop으로 바뀌었고 그 일은 효과가 있었다. – Billy

관련 문제