Mam program wiersza poleceń Cocoa, w którym próbuję uruchomić program NSTask
(tshark
, aby monitorować sieć) i pobierać z niego dane w czasie rzeczywistym. Zrobiłem więc NSFileHandle , zadzwonić pod numer waitForDataInBackgroundAndNotify
, aby wysłać powiadomienia, a następnie zarejestrować moją klasę pomocy w centrum powiadomień, aby przetworzyć dane, ale żadne powiadomienie nie zostanie wysłane do mojej klasy pomocy.Pobieranie danych z NSTask w czasie rzeczywistym za pomocą powiadomień nie działa
Czy ktoś ma pojęcie, co może być nie tak?
góry dzięki
Oto mój kod:
#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: Kiedy Odkomentuj skomentował fragment kodu i usunąć wszystkie tego powiadomienia rzeczy, wszystkie żądane dane są pobierane z uchwytu pliku po zakończenie zadania.
Zastanawiam się również, czy problem nie może być w rzeczywistości, że mój program jest "Narzędzie wiersza poleceń", więc nie jestem pewien, czy uruchomiono pętlę - jak mówi dokumentacja Apple jest potrzebna (w waitForDataInBackgroundAndNotify wiadomość NSFileHandle):
Musisz wywołać tę metodę z wątku, który ma aktywną pętlę uruchamiania.
Naprawdę powinieneś zrobić bardziej konkretny komunikat 'addObserver: selektor: name: object:'. Aktualnie logujesz się do * dowolnego * powiadomienia, a nie tylko do powiadomienia "NSFileHandleReadCompletionNotification". –
Pętla uruchamiania jest niejawnie tworzona w razie potrzeby, więc można bezpiecznie założyć, że "ma [a] uruchamianą pętlę", ale trzeba ją uruchomić. Aplikacja uruchomiłaby pętlę uruchamiania, więc wszystko, co musisz zrobić, to zwrócić, ale w narzędziu wiersza poleceń musisz uruchomić pętlę uruchamiania samodzielnie. Zalecam używanie NSFileHandle do odczytu ze standardowego wejścia, i robienie tego, co powiedziałem w mojej odpowiedzi, aby uruchomić pętlę uruchamiania, dopóki zadanie nie zostanie zakończone. –
@PeterHosey Dobry pomysł - dziękuję. Próbowałem to zrobić, ale nie działało. Więc cofnąłem się do prostego, pominiętego zatrzymania i wpadłem na to (http://pastebin.com/qnhaUAjp) (zauważyłem również, że dane przekazywane przez 'NSFileHandle' są w jakiś sposób buforowane - nie wiem jak się pozbyć) Po uruchomieniu czeka chwilę, a następnie zapisuje "Pakiety złapane" raz - potem nic. Jeśli odkomentuję 1, to czeka, a następnie napisz "Pakiet złapany" nieograniczoną ilość razy.I wreszcie, gdy próbuję wyodrębnić dane i odkomentować _2 -5_ czeka chwilę, pisze linie _2 i 3_, a następnie zawiesza się. Nie ma awarii, nie ma błędu, po prostu nie wyodrębniaj danych. – user1023979