7

私はNSTaskプログラム(ネットワークを監視するためにtshark)を実行し、リアルタイムでそのデータを取得しようとするココアコマンドラインプログラムを取得しました。そこで、私は NSFileHandle を作成し、通知を送信してから、ヘルプセンターを通知センターに登録してデータを処理しますが、ヘルプクラスに通知は1つも送信されません。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; 
} 

編集:私は、コードのコメントセクションのコメントを解除し、すべてのその通知のものを削除すると、必要なすべてのデータは、後にファイルハンドルから抽出されていますタスクフィニッシュ。

私のプログラムは「コマンドラインツール」なので、実際に問題が解決できないのではないかと思っていたので、ループが実行されているかどうかわかりません。AppleのマニュアルにはNSFileHandleのwaitForDataInBackgroundAndNotifyメッセージ):

アクティブな実行ループを持つスレッドからこのメソッドを呼び出す必要があります。

+0

本当にその 'addObserver:selector:name:object:'メッセージをより具体的にするべきです。あなたは現在、NSFileHandleReadCompletionNotification'通知だけでなく* any *通知にサインアップしています。 –

+0

実行ループは必要に応じて暗黙的に作成されるため、「実行ループがある」と思っても安全に実行できますが、実行する必要があります。アプリケーションは実行ループを実行するので、実行する必要があるのはリターンですが、コマンドラインツールでは実行ループを自分で実行する必要があります。 NSFileHandleを使用して標準入力から読み込むことをお勧めします。また、タスクが終了するまで実行ループを実行するために私が答えて言ったことを実行することをお勧めします。 –

+0

@PeterHosey良いアイデア - ありがとう。私はこれをやろうとしたが、うまくいかなかった。だから私は単純な、停止を省略し、[これは(http://pastebin.com/qnhaUAjp)(私はまた、NSFileHandleによって渡されたデータが何とかバッファリングされて気づいた - 私が1のコメントを外すと、パケットが無制限に捕らえられたと書いています。最後に、データを抽出してコメントを外してみると、_2 -5_それはしばらく待って、行_2と3_を書き込んだ後、フリーズします。いいえ、クラッシュはありません。エラーはありません。データを抽出しないでください。 – user1023979

答えて

1

タスクの起動後すぐにプログラムが終了します。あなたは仕事をwait until exitに伝える必要があります。実行ループが実行され、子プロセスが終了するのを待って、同時にファイルハンドルがパイプを監視できるようにします。タスクが終了すると、メソッドが戻り、mainの最後に進むことができます。

+0

私はコード全体を投稿する必要があります。私は自分の答えを編集しました。今すぐ見ることができます。自分のプログラムから手動でタスクを停止する可能性をユーザに与えています。私は 'waitUntilExit'を呼び出せばそれはできないと思います。私はまた、タスク(コメント欄)を停止した後にファイルハンドラからデータを抽出しようとしましたが、それは完全に機能しました。 – user1023979

+0

「私は私の答えを編集しました」と言ったとき、「私は私の質問を編集しました」 - 申し訳ありません – user1023979

0

非同期stdinを実装する方法を示すサンプルコード& NSTaskでデータを処理するstderrストリーム(改善の余地があるかもしれません)

8

10.7以降に新しいAPIが追加されました。したがって、NSNotificationsの使用を避けることができます。

task.standardOutput = [NSPipe pipe]; 
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) { 
    NSData *data = [file availableData]; // this will read to EOF, so call only once 
    NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 

    // if you're collecting the whole output of a task, you may store it on a property 
    [self.taskOutput appendData:data]; 
}]; 

おそらくあなたはtask.standardErrorのために上記と同じを繰り返します。

重要:

あなたのタスクが終了すると、あなたはnilにreadabilityHandlerブロックを設定する必要があります。それ以外の場合は、読み取りが停止しないため、CPU使用率が高くなります。

[task setTerminationHandler:^(NSTask *task) { 

    // do your stuff on completion 

    [task.standardOutput fileHandleForReading].readabilityHandler = nil; 
    [task.standardError fileHandleForReading].readabilityHandler = nil; 
}]; 

これは、すべての非同期である(そして、あなたがそれを行う必要があり非同期)ので、あなたの方法は^完了ブロックを持っている必要があります。

関連する問題