2012-07-24 18 views
6

मेरे पास एक प्रोग्राम है जो एक मेजबान (कच्चे सॉकेट का उपयोग करके) में टीसीपी एसवाईएन पैकेट का एक सेट भेजता है और प्रतिक्रिया प्राप्त करने के लिए libpcap (फ़िल्टर के साथ) का उपयोग करता है। मैं इसे एसिंक्रोनस I/O ढांचे में कार्यान्वित करने की कोशिश कर रहा हूं, लेकिन ऐसा लगता है कि libpcap में कुछ प्रतिक्रियाएं अनुपलब्ध हैं (अर्थात् टीसीपी एसवाईएन और प्रतिक्रिया के बीच 100 microseconds से कम होने पर श्रृंखला के पहले पैकेट)।असिंक्रोनस libpcap: पैकेट खोना?

pcap_t* pcap = pcap_open_live(NULL, -1, false, -1, errorBuffer); 
pcap_setnonblock(pcap, true, errorBuffer); 

तो मैं (filterExpression स्ट्रिंग पर निहित) एक फ़िल्टर जोड़ें:

struct bpf_program filter; 
pcap_compile(pcap, &filter, filterExpression.c_str(), false, 0); 
pcap_setfilter(pcap, &filter); 
pcap_freecode(&filter); 

और एक पाश पर, प्रत्येक पैकेट भेजने के बाद, मुझे पता है कि चयन विकल्प का उपयोग PCAP संभाल इस तरह सेटअप है अगर मैं libpcap से पढ़ सकते हैं:

int pcapFd = pcap_get_selectable_fd(pcap); 
fd_set fdRead; 
FD_ZERO(&fdRead); 
FD_SET(pcapFd, &fdRead); 
select(pcapFd + 1, &fdRead, NULL, NULL, &selectTimeout); 

और यह पढ़ें:

if (FD_ISSET(pcapFd, &fdRead)) { 
    struct pcap_pkthdr* pktHeader; 
    const u_char* pktData; 
    if (pcap_next_ex(pcap, &pktHeader, &pktData) > 0) { 
     // Process received response. 
    } 
    else { 
     // Nothing to receive (or error). 
    } 
} 

जैसा कि मैंने पहले कहा था, कुछ पैकेट मिस्ड हैं ("प्राप्त करने के लिए कुछ नहीं" में गिर रहे हैं)। मुझे पता है कि ये पैकेट वहां हैं, क्योंकि मैं उन्हें एक तुल्यकालिक फैशन पर पकड़ सकता हूं (tcpdump या pcap_loop चल रहे थ्रेड का उपयोग कर)। क्या मुझे यहां कुछ विवरण याद आ रहा है? या यह libpcap के साथ एक मुद्दा है?

+0

यह मामला हो सकता है कि आप बहुत से अनुरोध बहुत तेज़ी से भेज रहे हैं, और सर्वर प्रतिक्रिया तेजी से भेज रहा है, तो आप उन्हें ओएस के नेटवर्क बफर को ओवरलोड करने और पैकेट छोड़ने के लिए संभाल सकते हैं। या यह संभव है कि आप रिसीवर सॉकेट प्रारंभिक प्रतिक्रियाओं को संभालने के लिए समय पर स्थापित नहीं हो। क्या आप यह सत्यापित कर सकते हैं कि आप जो प्रतिक्रियाएं प्राप्त कर रहे हैं, वे वास्तव में वहां जा रहे हैं? Todo यह एक ही इंटरफेस पर एक साथ अपने आवेदन के रूप में tcpdump रन।यदि आप उन सभी पैकेट्स को देखते हैं जिन्हें आप टीसीपीडम्प में उम्मीद करते हैं और आपके आवेदन में नहीं, तो आपके ऊपर उपरोक्त समस्याओं में से एक हो सकती है। – ryanbwork

+0

मैंने पहले से ही यह किया है (तरफ tcpdump, लेकिन एक अलग धागा pcap_loop भी), और सभी पैकेट वहाँ थे। इस प्रकार, मुझे विश्वास नहीं है कि मैं प्रतिक्रियाओं को बहुत तेजी से भेज रहा हूं। मैं कैसे बता सकता हूं कि मेरा रिसीवर सॉकेट (यानी libpcap) अभी तक सेटअप नहीं है? यह समझ में आता है क्योंकि खोए गए प्रतिक्रिया हमेशा पहले या दो होते हैं। –

+0

भले ही आप टीसीपीडम्प में पैकेट देखते हैं, फिर भी यदि वे आपके द्वारा प्राप्त की गई दर को संभाल नहीं सकते हैं तो भी उन्हें ओएस द्वारा छोड़ा जा सकता है। यदि आपका आवेदन पहले ही भेजा जा रहा है, तो आपका आवेदन शुरू हो रहा है, तो अपने सर्वर से प्रारंभिक प्रतिक्रिया भेजने से पहले कुछ महत्वपूर्ण देरी जोड़ने का प्रयास करें; यदि आप सफलतापूर्वक सभी प्रतिक्रियाएं प्राप्त करते हैं, तो आपको अपनी समस्या मिल गई है। – ryanbwork

उत्तर

1

यह लिनक्स के तहत मेमोरी मैपिंग का उपयोग करके libpcap के साथ एक मुद्दा प्रतीत होता है। विवरण के लिए कृपया my other question देखें।

+0

तो, क्या आपने इस समस्या को हल किया है? libpcap के लिए मेमोरी मैपिंग कैसे सक्षम करें? – misteryes

1

हैं pcap_t के लिए एफडी select() द्वारा पठनीय रूप में रिपोर्ट किया गया है (या poll() या जो कुछ भी कॉल आप उपयोग कर रहे/तंत्र), कोई गारंटी नहीं है इसका मतलब है कि यह है कि केवल एक पैकेट को रोके बिना पढ़ा जा सकता है नहीं है।

यदि आप pcap_next_ex() का उपयोग करते हैं, तो आप केवल एक पैकेट पढ़ेंगे; यदि पढ़ने के लिए एक से अधिक पैकेट उपलब्ध हैं, तो, यदि आप एक और select() करते हैं, तो इसे तुरंत वापस करना चाहिए, एफडी को फिर से पठनीय होने की रिपोर्ट करना, इस मामले में आप संभावित रूप से pcap_next_ex() पर कॉल करेंगे, और इसी तरह। इसका अर्थ यह है कि प्रति पैक कम से कम एक सिस्टम कॉल (select()), और संभावित रूप से अधिक कॉल, आप किस ओएस के क्या संस्करण कर रहे हैं और आपके पास libpcap का कौन सा संस्करण है, इस पर निर्भर करता है।

यदि, इसके बजाय, आपको pcap_dispatch() पर कॉल करने के लिए 1 के पैकेट-गिनती तर्क के साथ कॉल करना था, तो वह कॉल उन सभी पैकेट को वापस कर देगा जिन्हें एक एकल पठन ऑपरेशन के साथ प्राप्त किया जा सकता है और उनमें से सभी को संसाधित किया जा सकता है, इसलिए, सबसे अधिक प्लेटफॉर्म, यदि आप कई पैकेट उपलब्ध हैं (जो, उच्च नेटवर्क यातायात के साथ, यदि आप अपने प्रोग्राम को एक एसईएन बाढ़ के साथ परीक्षण कर रहे हैं, तो यह मामला होने की संभावना है) के साथ आप एक या दो सिस्टम कॉल के साथ कई पैकेट प्राप्त कर सकते हैं। ।

इसके अलावा, Linux सिस्टम का समर्थन करने वाले स्मृति-मैप किया गया पैकेट पर कब्जा (मुझे लगता है कि सब 2.6 और बाद कर्नेल करते हैं, और सबसे नहीं तो सब 2.4 कर्नेल करते हैं), और libpcap के नए संस्करण के साथ, pcap_next_ex() प्रतिलिपि बनाने के लिए है पर कर्नेल को पैकेट को संसाधित करने वाले कोड के नीचे से पैकेट को बदलने से बचने के लिए पैकेट का और अनिश्चित अवधि के लिए रिंग बफर में एक स्लॉट "लॉक अप" से बचने के लिए, इसलिए इसमें एक अतिरिक्त प्रति शामिल है।

+0

+1 उपयोगकर्ताओं के लिए एक आम जाल एसिंक I/O से परिचित नहीं है :) आपको पढ़ना जारी रखना चाहिए!)) –

+0

हालांकि यह उपयोगी जानकारी है, यह मामला यहां नहीं है। मुख्य समस्या 'select' सक्रिय' pcap_t' पर आरोप लगा रही है और फिर 'pcap_next_ex' शून्य लौटा रही है। ध्यान दें कि "खोए गए पैकेट" "प्राप्त करने के लिए कुछ भी नहीं" में गिर रहे हैं। –

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