2016-08-12 8 views
9

मैंने एक एमएफसी सी ++ ऐप लिखा है जहां मेरी क्लाइंट प्रक्रिया मेरी सर्वर प्रक्रिया में एक टीसीपी MyCAsyncSocket::Connect करता है। सर्वर प्रक्रिया MyCAsyncSocket::OnAccept के साथ प्रतिक्रिया देती है जो Detach निर्धारित सॉकेट के रूप में सॉकेट करता है, जो उस सॉकेट को Attach es सॉकेट बनाता है, जो तब भेजा जा रहा डेटा पढ़ता है। एमएसडीएन निर्धारित करता है कि Detach के बाद m_hSocket को NULL पर सेट किया जाना चाहिए।कोई सर्वर ऑन क्लाइंट अधिसूचना क्लाइंट करते समय दूसरी बार कनेक्ट करें

यह ठीक काम करता है, लेकिन केवल एक बार। दूसरी बार ग्राहक उसी सॉकेट पते पर Connect पर प्रयास करता है, OnAccept अधिसूचना नहीं होती है।

void MyCAsyncSocket::OnAccept(int nErrorCode) 
{ 
    BOOL socketResult = FALSE; 

    CAsyncSocket syncSocket; 

    Accept(syncSocket); 
    AsyncSelect(FD_READ | FD_CLOSE); 

    SOCKET socket = syncSocket.Detach(); 
    m_hSocket = NULL; // prescribed by msdn 

    ... // go attach the socket in a worker thread, read the socket and do work 

    // try to re-establish listener. 
    ...Create(// error: attempt 2: ASSERT(m_hSocket == INVALID_SOCKET) 
    endPoint.portNumber, // ok: same as client port number 
    SOCK_STREAM, 
    FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE, 
    endPoint.ipAddress // ok: same as client ip address 
); 

    ...Listen(); // error: attempt 1: no error case, but still doesn't work 


    CAsyncSocket::OnAccept(nErrorCode); 
} 

प्रयास 1:: यहाँ सर्वर कोड है OnAccept में Detach मैं एक Listen साथ पालन करने का प्रयास करने के बाद, लेकिन मैं इस सुनने त्रुटि मिलती है: "WSAENOTSOCK: वर्णनकर्ता सॉकेट नहीं है।" निश्चित नहीं इसका क्या मतलब।

प्रयास 2: मैं तो अनुवर्ती Listen से पहले एक Create कर की कोशिश की, लेकिन यह एक ज़ोर का कारण: ASSERT(m_hSocket == INVALID_SOCKET); जो के रूप में परिभाषित किया गया है:

/* 
* This is used instead of -1, since the 
* SOCKET type is unsigned. 
*/ 
#define INVALID_SOCKET (SOCKET)(~0) 

प्रोटोटाइप कोड मैं केवल श्रोता सॉकेट नष्ट में और इसे स्क्रैच से फिर से बनाया गया है, लेकिन उत्पादन कोड के लिए, Detach आईएनजी और Attach आईएनजी के पूरे विचार के बाद यह स्वीकार्य नहीं है कि सॉकेट थ्रेड की सुनने की क्षमता माइक्रोसॉंड से अधिक के लिए कभी बाधित नहीं होती है।

क्या कोई जानता है कि बाद के Connect आयनों के लिए सॉकेट तैयार करने के लिए उचित अर्थशास्त्र क्या होना चाहिए? सुन सॉकेट पर | (FD_CLOSE FD_READ) - और मुझे लगता है कि आप वास्तव में कॉल करने के लिए है कि हाल में स्वीकार किए जाते हैं सॉकेट (syncSocket) पर चाहते

उत्तर

2

यदि मैं यह सही ढंग से पढ़ रहा हूँ, आप AsyncSelect कहते हैं।

मुझे उम्मीद है कि AsyncSelect (FD_READ | FD_CLOSE) को कॉल करना सुनवाई सॉकेट पर FD_ACCEPT अधिसूचना को साफ़ कर सकता है - इस प्रकार यह सुनिश्चित करना कि सुनवाई सॉकेट में भविष्य के कनेक्शन किए जाने पर कोई ऑनएसेप्ट नहीं कहा जाता है।

आगे - जब आप ऊपर m_hSocket = NULL सेट करते हैं, तो आप सॉकेट सुनने के संभाल नहीं कर रहे हैं, न कि नए स्वीकृत सॉकेट (सिंक सॉकेट) की।

इसके अलावा, अगर मैं एमएसडीएन सही ढंग से पढ़ रहा हूं (https://msdn.microsoft.com/en-us/library/05sz8hz8.aspx), तो डिटेच() विधि स्वयं प्रासंगिक हैंडल को बाहर कर देती है, और आपको इसे स्वयं करने की आवश्यकता नहीं है। [है और न ही, मैं उम्मीद कर सकते हैं आप - m_hSocket चाहिए के बाद से syncSocket के एक निजी सदस्य होना]

मैं अपने OnAccept कोड अधिक की तरह लग रहे करने के लिए उम्मीद करेंगे:

void MyCAsyncSocket::OnAccept(int nErrorCode) 
{ 
    BOOL socketResult = FALSE; 

    CAsyncSocket syncSocket; 

    Accept(syncSocket); 

    SOCKET socket = syncSocket.Detach(); 

    ... // go attach the socket in a worker thread, which reads the socket and does work 

} 
+0

वर्क्स अब। मैंने 'AsyncSelect (FD_READ | FD_CLOSE) दोनों को हटा दिया; 'और' m_hSocket = NULL; 'कथन, और दूसरी' ऑनसेप्ट 'अधिसूचना के माध्यम से आया। बेशक, 'AsyncSelect (FD_ACCEPT | FD_READ | FD_CLOSE);' भी काम करता है। अच्छा पकड़ा। – rtischer8277

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