У меня есть программа командной строки Cocoa, в которой я пытаюсь запустить программу NSTask
(tshark
10 для мониторинга сети) и получать данные из нее в режиме реального времени. Поэтому я делаю NSFileHandle , звоните waitForDataInBackgroundAndNotify
, чтобы отправлять уведомления, а затем зарегистрировать мой класс справки в Центре уведомлений для обработки данных, но ни одно уведомление не отправляется в мой класс справки.Получение данных из NSTask в режиме реального времени с использованием уведомлений не работает
Есть ли у кого-нибудь представление о том, что может быть неправильным?
Заранее спасибо
Вот мой код:
#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: Когда я раскомментировать прокомментировал раздел кода и удалить все, что уведомление вещи, все нужные данные извлекаются из дескриптора файла после завершение задачи.
Мне также интересно, если проблема не может быть на самом деле, что моя программа «Инструмент командной строки», поэтому я не уверен, что она запускает цикл - по мере того, как требуется документация Apple (в сообщении waitForDataInBackgroundAndNotify от NSFileHandle):
Вы должны вызвать этот метод из потока, который имеет активный цикл цикла.
Вы действительно должны сделать это 'addObserver: selector: name: object:' message более конкретным. Вы в настоящее время подписываетесь на * любое * уведомление, а не только на уведомление NSFileHandleReadCompletionNotification. –
Цикл выполнения неявно создается при необходимости, поэтому вы можете смело предположить, что «он имеет [цикл] запуска», но вам нужно его запустить. Приложение будет запускать цикл цикла для вас, поэтому все, что вам нужно сделать, это вернуть, но в инструменте командной строки вы должны запустить цикл выполнения самостоятельно. Я рекомендую использовать NSFileHandle для чтения со стандартного ввода, а также делать то, что я сказал в своем ответе, чтобы запустить цикл выполнения, пока задача не завершится. –
@PeterHosey Хорошая идея - спасибо. Я пытался это сделать, но не работал. Поэтому я отступил к простой, опустившейся остановке и придумал [это] (http://pastebin.com/qnhaUAjp) (я также заметил, что данные, переданные 'NSFileHandle', как-то буферизованы - не знают, как избавиться из этого) После запуска он ждет некоторое время, а затем пишет «Пакет пойман» один раз - тогда ничего. Если я раскомментирую 1, то он ждет, а затем напишет «Пакет поймал» неограниченное количество раз. И наконец, когда я пытаюсь извлечь данные и раскомментировать _2 -5_ он ждет некоторое время, пишет строки _2 & 3_, а затем зависает. Не сбой, никаких ошибок, просто не извлекайте данные. – user1023979