7

काम नहीं करता है मुझे कोको कमांड लाइन प्रोग्राम मिला है जिसमें मैं NSTask प्रोग्राम (tshark नेटवर्क की निगरानी करने के लिए) चलाने का प्रयास करता हूं और वास्तविक समय में डेटा प्राप्त करता हूं। तो मैं NSFileHandle बना देता हूं, अधिसूचनाएं भेजने के लिए waitForDataInBackgroundAndNotify पर कॉल करें और फिर मेरी सहायता कक्षा को डेटा संसाधित करने के लिए अधिसूचना केंद्र में पंजीकृत करें, लेकिन मेरी सहायता कक्षा में एक भी अधिसूचना नहीं भेजी गई है।नोटिफिकेशन का उपयोग करके रीयल-टाइम में एनएसटीस्क से डेटा प्राप्त करना

क्या किसी के पास कोई विचार है कि क्या गलत हो सकता है?

अग्रिम

यहाँ धन्यवाद मेरी कोड है:

#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; 
} 

संपादित करें: जब मैं कोड की धारा टिप्पणी की है और सभी कि अधिसूचना सामान हटाना टिप्पणी हटाएं, सभी वांछित डेटा के बाद फ़ाइल हैंडल से निकाले जाते हैं कार्य खत्म

मैं भी सोच रहा था, अगर समस्या वास्तव में नहीं हो सकती है, तो मेरा प्रोग्राम 'कमांड लाइन टूल' है, इसलिए मुझे यकीन नहीं है कि इसमें लूप चलाया गया है - क्योंकि ऐप्पल दस्तावेज कहता है (प्रतीक्षा करेंForDataInBackground और NSFileHandle का संदेश):

आपको इस विधि को उस थ्रेड से कॉल करना होगा जिसमें सक्रिय रन लूप है।

+0

आपको वास्तव में वह 'addObserver: selector: name: object:' संदेश अधिक विशिष्ट बनाना चाहिए। आप वर्तमान में 'NSFileHandleReadCompletionNotification' अधिसूचना न केवल * किसी * अधिसूचना के लिए साइन अप कर रहे हैं। –

+0

रन लूप को आवश्यकता होने पर पूरी तरह से बनाया गया है, इसलिए आप सुरक्षित रूप से "यह [ए] रन लूप" मान सकते हैं, लेकिन आपको इसे चलाने की आवश्यकता है। एक एप्लिकेशन आपके लिए रन लूप चलाएगा, इसलिए आपको केवल इतना करना होगा कि वापस लौटना होगा, लेकिन कमांड लाइन टूल में, आपको रन लूप को स्वयं चलाना होगा। मैं मानक इनपुट से पढ़ने के लिए NSFileHandle का उपयोग करने की सलाह देता हूं, और जब तक कार्य बाहर निकलता है तब तक रन लूप चलाने के लिए मैंने जो जवाब दिया है, वह कर रहा हूं। –

+0

@ पीटर होसे अच्छा विचार - धन्यवाद। मैंने ऐसा करने की कोशिश की लेकिन काम नहीं किया। तो मैं वापस सरल, छोड़े गए स्टॉप पर वापस चला गया और [इस] (http://pastebin.com/qnhaUAjp) के साथ आया (मैंने यह भी देखा कि 'NSFileHandle' द्वारा पारित डेटा किसी भी तरह से buffered हैं - पता नहीं कैसे छुटकारा पाने के लिए इसके बाद) यह शुरू होने के बाद, यह थोड़ी देर इंतजार करता है और फिर 'पैकेट पकड़ा' लिखता है - फिर कुछ भी नहीं। अगर मैं 1 को अपूर्ण करता हूं तो यह इंतजार करता है और फिर 'पैकेट पकड़ा' असीमित समय लिखता है। और आखिरकार जब मैं डेटा और असम्बद्धता निकालने का प्रयास करता हूं _2 -5_ यह थोड़ी देर इंतजार करता है, रेखाएं _2 और 3_ लिखता है और फिर फ्रीज करता है। कोई दुर्घटना नहीं, कोई त्रुटि नहीं, बस डेटा निकालें नहीं। – user1023979

उत्तर

1

आपका प्रोग्राम कार्य शुरू करने के तुरंत बाद खत्म हो जाता है। आपको कार्य को wait until exit पर बताना होगा। वह रन लूप चलाएगा, बच्चे की प्रक्रिया से बाहर निकलने की प्रतीक्षा करेगा और संयोग से फाइल हैंडल को पाइप की निगरानी करने में सक्षम करेगा। जब कार्य बाहर निकलता है, तो विधि वापस आ जाएगी और आप main के अंत तक आगे बढ़ सकते हैं।

+0

मुझे पूरा कोड पोस्ट करना चाहिए। मैंने अपना जवाब संपादित किया - अब आप देख सकते हैं कि मैं अपने कार्यक्रम से मैन्युअल रूप से कार्य को रोकने के लिए उपयोगकर्ता की संभावना दे रहा हूं। मुझे लगता है कि अगर मैं 'waitUntilExit' कहूंगा तो यह संभव नहीं होगा। मैंने कार्य को रोकने के बाद फ़ाइल हैंडलर से डेटा निकालने का भी प्रयास किया (टिप्पणी अनुभाग) और यह पूरी तरह से काम किया। – user1023979

+0

और जब मैं कहता हूं कि 'मैंने अपना जवाब संपादित किया' मेरा मतलब है 'मैंने अपना प्रश्न संपादित किया' - क्षमा करें – user1023979

0

asynctask.m पर एक नज़र डालें, नमूना कोड जो दिखाता है कि एनएसटीस्क के साथ डेटा प्रोसेसिंग के लिए एसिंक्रोनस स्टडीन, stdout & stderr स्ट्रीम को कैसे कार्यान्वित किया जाए (हालांकि सुधार के लिए कमरा हो सकता है)।

8

10.7 के बाद से एक नया एपीआई है, इसलिए आप 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 के लिए एक ही ऊपर दोहराना चाहते हैं।

महत्वपूर्ण:

जब अपने कार्य समाप्त हो जाता है, तो आप नहीं के बराबर करने के लिए readabilityHandler ब्लॉक सेट करने के लिए; अन्यथा, आपको उच्च CPU उपयोग का सामना करना पड़ेगा, क्योंकि पठन कभी नहीं रुक जाएगा।

[task setTerminationHandler:^(NSTask *task) { 

    // do your stuff on completion 

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

यह सभी असीमित है (और आपको इसे async करना चाहिए), इसलिए आपकी विधि में^समापन ब्लॉक होना चाहिए।

संबंधित मुद्दे