Stream Kommunikation Mac<->iOS

  • Stream Kommunikation Mac<->iOS

    Ich versuche gerade, eine Stream-Kommunikation zwischen einem Mac (als Server) und iOS-Geräten als Clients aufzubauen.

    Quellcode

    1. NSNetService *netService;
    2. NSInputStream *inputStream;
    3. NSOutputStream *outputStream;
    4. netService = [[NSNetService alloc] initWithDomain:@""
    5. type:@"_myservice._tcp."
    6. name:@"My Service"
    7. port:2801];
    8. [netService setDelegate:self];
    9. [netService publish];
    10. - (void)netServiceDidPublish:(NSNetService *)sender {
    11. [sender getInputStream:&inputStream outputStream:&outputStream];
    12. [inputStream setDelegate:self];
    13. [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    14. [inputStream open];
    15. [outputStream setDelegate:self];
    16. [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    17. [outputStream open];
    18. }
    Alles anzeigen

    LEider erhalte ich in - (void)stream: (NSStream *)theStream handleEvent: (NSStreamEvent)streamEvent immer zwei mal NSStreamEventErrorOccurred.

    Was mache ich falsch?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von DroneDeveloper ()

  • Zwei Ideen (ins Blaue):

    1. Sind nach Aufruf von [sender getInputStream:&inputStream outputStream:&outputStream];
    die Objekte hinter inputStream und outputStream eventuell nicht retained?


    2. Ist der zugrundeliegende Socket vielleicht schon wieder geschlossen, wenn

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

    aufgerufen wird?

    Dann probier mal folgendes:

    Quellcode

    1. [inputStream setProperty:(id)kCFBooleanFalse forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];


    direkt nach dem getInputStream Aufruf.
    Ewig erstaunt...
  • Soweit läuft nun alles.

    Allerdings scheint es so, als ob der Server (Mac) den Stream bzw. Socket nicht ordnungsgemäß schließt. Denn der Client (iPhone) erhält NSStreamEventEndEncountered nur nach dem exit() am Server.
    Der Server "schließt" den Stream und Socket folgendermaßen:

    Quellcode

    1. @property (strong, nonatomic) NSNetService *netService;
    2. @property (assign, nonatomic) CFSocketRef socketRef;
    3. @property (strong, nonatomic) NSInputStream *inputStream;
    4. @property (strong, nonatomic) NSOutputStream *outputStream;
    5. @synthesize netService;
    6. @synthesize socketRef = _socketRef;
    7. @synthesize inputStream;
    8. @synthesize outputStream;
    9. if (self.inputStream != nil) {
    10. [self.inputStream setDelegate:nil];
    11. [self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    12. [self.inputStream close];
    13. self.inputStream = nil;
    14. }
    15. if (self.outputStream != nil) {
    16. [self.outputStream setDelegate:nil];
    17. [self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    18. [self.outputStream close];
    19. self.outputStream = nil;
    20. }
    21. if (self.netService != nil) {
    22. [self.netService stop];
    23. self.netService = nil;
    24. }
    25. if (self.socketRef != NULL) {
    26. CFSocketInvalidate(self.socketRef);
    27. self.socketRef = NULL;
    28. }
    Alles anzeigen
  • ALso am iPhone läuft es wie folgt ab:

    The open has completed successfully. (NSInputStream)
    The open has completed successfully. (NSOutputStream)
    The stream can accept bytes for writing. (NSOutputStream)

    Erst wenn ich die komplette Server-App kille exit() kommt

    The end of the stream has been reached.

    Irgendein Stream oder Socket schließt sich also nicht richtig.
  • Quellcode

    1. - (void)_startReceive:(int)fd {
    2. assert(fd >= 0);
    3. assert(self.networkStream == nil);
    4. assert(self.outputStream == nil);
    5. CFReadStreamRef readStream;
    6. CFWriteStreamRef writeStream;
    7. CFStreamCreatePairWithSocket(NULL, fd, &readStream, &writeStream);
    8. assert(readStream != NULL);
    9. assert(writeStream != NULL);
    10. self.networkStream = (NSInputStream *)readStream;
    11. self.outputStream = (NSOutputStream *)writeStream;
    12. CFRelease(readStream);
    13. CFRelease(writeStream);
    14. [self.networkStream setProperty: (id)kCFBooleanTrue forKey: (NSString *)kCFStreamPropertyShouldCloseNativeSocket]; <--- Hier
    15. [self.networkStream setDelegate:self];
    16. [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    17. [self.networkStream open];
    18. [self.outputStream setProperty: (id)kCFBooleanTrue forKey: (NSString *)kCFStreamPropertyShouldCloseNativeSocket]; <--- Hier
    19. [self.outputStream setDelegate:self];
    20. [self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    21. [self.outputStream open];
    22. [self.stopServerButton setEnabled:YES];
    23. }
    Alles anzeigen


    So geht's.
    Mit lsof -p <PID> kannst du alle offenen Dateien und Ports ansehen.

    Chris
    Man macht einfach solange irgendwelche Dinge, bis man tot ist.
    Und dann bekommen die anderen Kuchen.