2009-07-24 13 views
6

मैं एक आईओ पूर्णता पोर्ट आधारित सर्वर (source code here) लिख रहा हूं, पाइथन में विंडोज़ डीएलएल एपीआई का उपयोग करके ctypes मॉड्यूल का उपयोग कर। लेकिन यह एपीआई का एक बहुत सी प्रत्यक्ष उपयोग है और यह प्रश्न उन लोगों पर निर्देशित है जिन्हें आईओसीपी का ज्ञान है, पायथन नहीं।आईओ पूर्णता पोर्ट कुंजी भ्रम

जैसा कि मैं CreateIoCompletionPort के लिए प्रलेखन को समझता हूं, आप अपनी "उपयोगकर्ता परिभाषित" समापन कुंजी निर्दिष्ट करते हैं जब आप इस फ़ंक्शन को फ़ाइल हैंडल (मेरे मामले में सॉकेट) के साथ कॉल करते हैं, तो आप बनाए गए IOCP से संबद्ध होते हैं। जब आप GetQueuedCompletionStatus को कॉल करने के लिए चारों ओर जाते हैं, तो आपको एक ओवरलैप्ड ऑब्जेक्ट के पॉइंटर के साथ एक पूर्णता कुंजी मान मिलता है। समापन कुंजी को पहचानना चाहिए कि ओवरलैप्ड ऑब्जेक्ट और अनुरोध पूरा हो गया है।

हालांकि, मान लीजिए कि मैं अपने CreateIoCompletionPort कॉल में एक ओवरलैप्ड ऑब्जेक्ट के साथ पूर्णता कुंजी के रूप में 100 में पास करता हूं। जब एक ही ओवरलैप्ड ऑब्जेक्ट में आईओओ पूरा हो जाता है और यह GetQueuedCompletionStatus के माध्यम से वापस आता है, तो इसके साथ पूर्ण होने वाली कुंजी बहुत बड़ी होती है और 100 के मूल मान के समान नहीं होती है।

क्या मैं गलत समझता हूं कि पूर्णता कुंजी कैसे काम करती है, या क्या मुझे उपरोक्त लिंक स्रोत स्रोत में गलत करना होगा?

उत्तर

1

GetQueuedCompletionStatus दो चीजें, OVERLAPPED संरचना और पूर्णता कुंजी देता है। समापन कुंजी प्रति-डिवाइस जानकारी का प्रतिनिधित्व करती है, और OVERLAPPED संरचना प्रति-कॉल जानकारी का प्रतिनिधित्व करती है। समापन कुंजी को CreateIoCompletionPort पर कॉल में दिए गए मिलान से मेल खाना चाहिए। आम तौर पर, आप समापन कुंजी के रूप में कनेक्शन के बारे में जानकारी युक्त एक संरचना के लिए एक सूचक का उपयोग करेंगे।

ऐसा लगता है कि आप completionKey के साथ कुछ भी नहीं कर रहे हैं जैसा कि GetQueuedCompletionStatus द्वारा लौटाया गया है।

मैं तुम्हें अनुमान लगा रहा हूँ हैं:

if completionKey != acceptKey: 
    Cleanup() 
    ... 

संपादित करें:

करता अजगर किसी भी तरह जानते हैं कि OVERLAPPED संरचना CreateAcceptSocket में बनाया Win32 एपीआई द्वारा अतुल्यकालिक रूप से इस्तेमाल किया जा रहा है और यह जीसी होने से रोक ' घ?

+0

"मान लीजिए कि मैं अपने CreateIoCompletionPort कॉल में एक ओवरलैप्ड ऑब्जेक्ट के साथ पूर्णता कुंजी के रूप में 100 में पास करता हूं। जब एक ही ओवरलैप्ड ऑब्जेक्ट का आईओ पूरा हो जाता है और यह GetQueuedCompletionStatus के माध्यम से वापस आता है, तो इसके साथ पूर्णता कुंजी बहुत बड़ी और बार्स होती है 100 के मूल मूल्य के साथ कोई समानता नहीं है। " मेरे प्रश्न से और मैं स्रोत कोड में इसकी तुलना क्यों नहीं कर रहा हूं। शायद आप ओवरलैप्ड ऑब्जेक्ट को कचरा प्राप्त करने के बारे में सही हैं, लेकिन यह सवाल के लिए अप्रासंगिक है। –

0

समस्या यह है कि मैं समापन कुंजी कैसे पारित कर रहा हूं। समापन कुंजी तर्क एक सूचक है, फिर भी यह उस सूचक को वापस भेजता है जो मूल्य की ओर इशारा नहीं करता - कम से कम मुझे थोड़ा उलझन में डालता है।

स्वीकार्य कनेक्शन ओवरलैप्ड पैकेट के लिए पारित होने वाली समाप्ति कुंजी भी सुनवाई सॉकेट की है - स्वीकृत सॉकेट नहीं।

4

मुझे रोजमर्रा की प्रैक्टिस में जो मिला है वह यह है कि OVERLAPPED परिणाम पर ध्यान केंद्रित करना सबसे अच्छा है, क्योंकि यह अपरिवर्तित होगा।

struct CompletionHandler 
{ 
    OVERLAPPED dummy_ovl; 
    /* Stuff that actually means something to you here */ 
}; 

आप IOCP के लिए कुछ पोस्ट करते हैं (चाहे मैं/हे कॉल या Win32 एपीआई के माध्यम से सिर्फ एक पोस्ट के माध्यम से), जिसे आप पहले बनाना एक: एक ही रास्ता है कि आप इसे प्रभावी ढंग से उपयोग कर सकते हैं की तरह निम्नलिखित कुछ है करने के लिए है CompletionHandler ऑब्जेक्ट जिसे आप कॉल को ट्रैक करने के लिए उपयोग करेंगे, और उस ऑब्जेक्ट का पता OVERLAPPED* पर डालें।

CompletionHander my_handler; 
// Fill in whatever you need to in my_handler 
// Don't forget to keep the original my_handler! 

// I/O call goes here, and for OVERLAPPED* give: (OVERLAPPED*)&my_handler 

इस तरह, जब आप OVERLAPPED परिणाम तुम सब करने की है CompletionHandler और देखा करने के लिए वापस यह डाला जाता है मिलता है! आपके पास कॉल का मूल संदर्भ है।

OVERLAPPED* from_queued_completion_status; 
// Actually get a value into from_queued_completion_status 

CompletionHandler* handler_for_this_completion = (CompletionHandler*)from_queued_completion_status; 
// Have fun! 
एक वास्तविक दुनिया सेटिंग में अधिक जानकारी के लिए

, विंडोज (ver 1.42 header here) के लिए ASIO के बूस्ट के कार्यान्वयन की जाँच करें। से प्राप्त होने वाले OVERLAPPED पॉइंटर के सत्यापन जैसे कुछ विवरण हैं, लेकिन फिर से, लागू करने के लिए एक अच्छे तरीके के लिए लिंक देखें।

0

प्राप्ति कुंजी एक सूचक नहीं है - यह कई प्रकार के ULONG_PTR है, जिसका अर्थ है "एक सूचक का आकार पूर्णांक" है, इसलिए यह x86 पर 32-बिट और x64 पर 64-बिट्स है। टाइपनाम नाम उलझन में है, लेकिन जब Win32 टाइपनाम एक पॉइंटर का संदर्भ लेते हैं तो वे नाम के सामने एक पी रखते हैं, अंत में नहीं।

0

यदि आपका आवेदन मल्टीथ्रेडिंग है, तो सुनिश्चित करें कि आप जिस समापन कुंजी को पारित कर रहे हैं वह या तो स्टैक के बजाय ढेर पर ऑब्जेक्ट करने के लिए स्थिर या सूचक मूल्य है। आपके उदाहरण में जहां 100 निरंतर के रूप में पारित किया गया है, आपको कोई भी परिवर्तन कहना गलत होगा। लेकिन समस्या के रूप में यह हो सकता है कि आप CreateIoCompletionPort में सॉकेट हैंडल पास करें लेकिन इसे पुनर्प्राप्त करने के लिए GetQueuedCompletionStatus में हैंडल करने के संदर्भ में नहीं। आप

HANDLE socket; 
CreateIoCompletionPort((HANDLE)socket, existed_io_completion_port, (ULONG_PTR)socket, 0); 
/*some I/Os*/ 
... 

और

HANDLE socket; 
GetQueuedCompletionStatus(existed_io_completion_port, &io_bytes_done, (PULONG_PTR)&socket, &overlapped); 

करते हैं और ब्रैकेट में टाइप करने के लिए ध्यान देना कर सकते हैं।

1

आपको 'प्रति कनेक्शन' डेटा के रूप में पूर्णता कुंजी और (विस्तारित) ओवरलैप्ड संरचना 'प्रति i/o' ऑपरेशन के रूप में सोचना चाहिए।

कुछ लोग दोनों के लिए एक विस्तारित ओवरलैप्ड संरचना का उपयोग करते हैं और विस्तारित ओवरलैप्ड संरचना में उन्हें आवश्यक सभी जानकारी संग्रहीत करते हैं। मैंने हमेशा संदर्भित ऑब्जेक्ट को संग्रहीत किया है जो पूर्ण सॉफ़्ट में मेरी सॉकेट को लपेटता है और एक संदर्भित डेटा बफर को विस्तारित ओवरलैप्ड संरचना के रूप में संदर्भित करता है। यदि आप रुचि रखते हैं तो आप some example IOCP code in C++ here देख सकते हैं।

पूर्णता कुंजी प्रभावी ढंग से डेटा के लिए एक अपारदर्शी संभाल है जो सॉकेट पर पूरा होने पर I/O समापन प्रणाली आपको वापस देगी।