Ho ricevuto un programma da riga di comando Cocoa nel quale provo a eseguire il programma NSTask
(tshark
per monitorare la rete) e ottenere i dati da esso in tempo reale. Così faccio un NSFileHandle , chiama waitForDataInBackgroundAndNotify
per inviare notifiche e poi registro la mia classe di aiuto al Centro di notifica per elaborare i dati, ma non una singola notifica viene inviata alla mia classe di aiuto.Ottenere dati da NSTask in tempo reale usando le notifiche non funziona
Qualcuno ha un'idea di cosa potrebbe essere sbagliato?
Grazie in anticipo
Ecco il mio codice:
#import <Foundation/Foundation.h>
#import <string>
#import <iostream>
@interface toff : NSObject {}
-(void) process:(NSNotification*)notification;
@end
@implementation toff
-(void) process:(NSNotification*)notification{
printf("Packet caught!\n");
}
@end
int main (int argc, const char * argv[]){
@autoreleasepool {
NSTask* tshark = [[NSTask alloc] init];
NSPipe* p = [NSPipe pipe];
NSFileHandle* read = [p fileHandleForReading];
toff* t1 = [[toff alloc] init];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[read waitForDataInBackgroundAndNotify];
[nc addObserver:t1 selector:@selector(process:) name:nil object:nil];
printf("Type 'stop' to stop monitoring network traffic.\n");
[tshark setLaunchPath:@"/usr/local/bin/tshark"];
[tshark setStandardOutput:p];
[tshark launch];
while(1){
std::string buffer;
getline(std::cin, buffer);
if(buffer.empty()) continue;
else if(buffer.compare("stop") == 0){
[tshark interrupt];
break;
}
}
//NSData* dataRead = [read readDataToEndOfFile];
//NSLog(@"Data: %@", dataRead);
//NSString* stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
//NSLog(@"Output: %@", stringRead);
}
return 0;
}
EDIT: Quando ho Rimuovere il commento commentato sezione di codice e cancellare tutta quella roba la notifica, tutti i dati desiderati vengono estratti dai file handle dopo fine compito.
Mi chiedevo anche, se il problema non può essere in realtà, che il mio programma è 'strumento di riga di comando', quindi non sono sicuro se ha eseguito il ciclo - come dice la documentazione di Apple è necessario (nel messaggio WaitForDataInBackgroundAndNotify di NSFileHandle):
È necessario chiamare questo metodo da un thread che ha un ciclo di esecuzione attivo.
Si dovrebbe davvero fare che il messaggio "addObserver: selector: nome: oggetto:' più specifico. Attualmente stai registrando per * qualsiasi * notifica, non solo la notifica 'NSFileHandleReadCompletionNotification'. –
Il ciclo di esecuzione viene creato in modo implicito quando necessario, quindi è possibile ipotizzare "ha [un] ciclo di esecuzione", ma è necessario eseguirlo. Un'applicazione eseguirà il ciclo di esecuzione per te, quindi tutto ciò che devi fare è tornare, ma in uno strumento da riga di comando, devi eseguire il ciclo di esecuzione da solo. Raccomando di usare NSFileHandle per leggere anche dall'input standard e fare ciò che ho detto nella mia risposta per eseguire il ciclo di esecuzione fino all'uscita dall'attività. –
@PeterHosey Buona idea - grazie.ho provato a farlo ma non ha funzionato. Così ho fatto un passo indietro verso il semplice, omesso arresto e ho trovato [questo] (http://pastebin.com/qnhaUAjp) (ho anche notato che i dati trasmessi da 'NSFileHandle' sono in qualche modo bufferizzati - non so come sbarazzarsi di esso) Dopo l'avvio, attende un po 'e poi scrive' Packet caught 'una volta - quindi niente. Se ho decommentato 1, allora attende e scrive' Packet caught 'volte illimitate. E infine quando provo ad estrarre i dati e il commento _2 -5_ aspetta un po ', scrive le righe _2 e 3_ e poi si blocca. Nessun incidente, nessun errore, solo non estrarre i dati. – user1023979