2011-11-30 6 views
6

विफल रहता है मेरा कार्य टीसीपी के माध्यम से जुड़े दो कंप्यूटरों के बीच खेले गए दो खिलाड़ी गेम को कार्यान्वित करना है। आवश्यकता में से एक यह है कि केवल विजेता को फिर से पसंद किया जाता है या नहीं। यदि सर्वर जीतता है और आगे नहीं खेलता है, तो क्लाइंट को सर्वर के रूप में पुनरारंभ करना चाहिए और नए कनेक्शन स्वीकार करना चाहिए।बाइंड()

मेरा दृष्टिकोण: यदि गेम खो गया है (क्लाइंट मोड में), तो सॉकफड बंद करें और दूसरा बनाएं। फिर SO_REUSEADDR का उपयोग करके रीबंडिंग की अनुमति देने के लिए सेटॉकॉप का उपयोग करें, फिर बाध्य कॉल करें।

int yes = 1; 
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) 
{ 
    perror("setsockopt"); 
} 

if (bind(sockfd, (struct sockaddr*)&svr, sizeof(svr)) == -1) 
{ 
    perror("server: bind"); 
} 

लेकिन फिर भी, मुझे वही "पता पहले से उपयोग में है" त्रुटि मिल रही है। मैंने सॉकेट को पुनर्जीवित करने से पहले 150 सेकंड के लिए सोने की कोशिश की है और यह विधि काम करती है।

नोट: मैं इसे उसी पीसी पर परीक्षण कर रहा हूं। यह दो लिंक किए गए पीसी पर काम कर सकता है लेकिन इसे एक ही पीसी पर काम करने की आवश्यकता है। कृपया मदद करे।

+2

के बाद अपने सर्वर को पुनरारंभ करने का प्रयास करते हैं, तो यह आपको "पता पहले से उपयोग में" त्रुटि संदेशों को प्राप्त करने में सक्षम बनाता है, कृपया अपना कोड दिखाएं (विशेष रूप से 'सेटॉकोपट() 'के आसपास का हिस्सा) ताकि हम सहायता कर सकें। –

+4

क्या आप वाकई क्लाइंट कोड में इसे फिर से बनाने का प्रयास करने से पहले सर्वर-साइड (सॉकेट सुनना) बंद कर रहे हैं? एक लिनक्स सिस्टम पर, "netstat -tlp" को यह पहचानने के लिए एक टीसीपी पोर्ट खोलने के लिए क्या पता चलाना चाहिए ... – BRFennPocock

+0

आप एक मशीन पर दो बार एक ही {पता, portnum} को बांधने का प्रयास करते हैं? आप क्या होने की उम्मीद करेंगे? – wildplasser

उत्तर

2

चूंकि आप इसे उसी सिस्टम पर चला रहे हैं, ऐसा लगता है कि आपके पास दौड़ की स्थिति है। क्लाइंट ने इसे बंद करने से ठीक पहले bind() सॉकेट की कोशिश कर रहा है (मान लीजिए कि सर्वर और क्लाइंट दोनों अपने सॉकेट पर SO_REUSEADDR सेट कर रहे हैं)।

आपको किसी प्रकार का हैंडशेक लागू करने की आवश्यकता है जो सर्वर को सुनने के सॉकेट को बंद करने के बाद क्लाइंट को सूचित करने की अनुमति देता है - शायद सर्वर को अंतिम सॉकेट से सक्रिय सॉकेट बंद करने से पहले सुनना सॉकेट बंद करना चाहिए?

+0

हां, सॉकेट बंद होने से पहले 1 सेकंड की देरी हुई और जब मैंने इसे पुनर्निर्मित करने का प्रयास किया तो कोई देरी नहीं हुई। यह अब पूरी तरह से अच्छी तरह से काम करता है! :) – tecfreak

1

SO_REUSEADDR केवल आप एक साथ एक अधिक एक विशिष्ट पता करने के लिए बाध्य है, यानी पहली बार सर्वर INADDR_ANY (सभी इंटरफ़ेस) पर सुनता है और बाद में सर्वर विभिन्न विशिष्ट इंटरफ़ेस पतों पर सुनने की अनुमति देता है।

दूसरा परिदृश्य तब होता है जब टीसीपी सॉकेट एक कनेक्शन स्वीकार करता है, जिसे उपयोग में रखा जाता है, लेकिन सुनना सॉकेट स्वयं बंद हो जाता है और फिर फिर से खोला जाता है - कहते हैं कि पैरेंट सर्वर प्रक्रिया निकलती है और फिर से शुरू होती है।

दोनों ही मामलों आप की जरूरत में हमेशा सुन सॉकेट पर SO_REUSEADDR विकल्प सेट इससे पहले कि आप bind(2) कहते हैं।

+0

तो .. इस के लिए कोई अन्य तरीका? मैं दोनों कॉल से पहले SO_REUSEADDR का उपयोग कर रहा हूं। – tecfreak

+0

अधिकांशतः इस विकल्प का उपयोग 1-2 मिनट प्रतीक्षा करने से बचने के लिए किया जाता है जब एक विशिष्ट बंदरगाह पर सर्वर को पुनरारंभ करते समय एक बंद बंद सॉकेट TIME_WAIT स्थिति में होता है। –

+0

हां, यह मेरा दूसरा बिंदु है। –

0

इस सॉकेट विकल्प को सेट करने से स्थानीय पता पुन: उपयोग की अनुमति मिलती है। यदि बंदरगाह से बांधने का प्रयास करते समय कोई समस्या आती है जिसे बंद कर दिया गया है लेकिन जारी नहीं किया गया है (TIME_WAIT द्वारा परिभाषित 2 मिनट तक लग सकता है)। संसाधन को तुरंत जारी करने और TIME_WAIT स्थिति के आसपास जाने के लिए SO_REUSEADDR सॉकेट विकल्प लागू करें। 0 = अक्षम, 1 = सक्षम करता है।

अन्य सॉकेट को इस बंदरगाह को बाध्य करने की अनुमति देता है, जब तक कि पहले से ही बंदरगाह से सक्रिय सक्रिय सॉकेट बाध्य न हो। जब आप क्रैश