2011-01-16 5 views
19

मैं सर्वर पर बड़ी संख्या में सॉकेट कनेक्शन खोलकर जावा सर्वर का परीक्षण लोड करने का प्रयास कर रहा हूं, प्रमाणीकरण , कनेक्शन बंद, फिर दोहराना। मेरा ऐप थोड़ी देर के लिए महान चलाता है लेकिन अंत में मैं:"java.net.BindException: पता पहले से उपयोग में है" लोड सॉकेट निर्माण और लोड परीक्षण के लिए विनाश करने की कोशिश करते समय

java.net.BindException: Address already in use: connect

प्रलेखन मैंने पढ़ा है के अनुसार, इस का कारण यह है कि बंद सॉकेट अभी भी स्थानीय बंद होने के बाद समय की अवधि के लिए उन्हें सौंपे गए पते पर कब्जा है() था बुलाया। यह ओएस निर्भर है लेकिन मिनटों के क्रम में हो सकता है। मैंने सॉकेट पर setReuseAddress(true) को कॉल करने की कोशिश की, उम्मीद है कि close() के तुरंत बाद उसका पता पुन: प्रयोज्य होगा। दुर्भाग्यवश यह मामला प्रतीत नहीं होता है।

सॉकेट निर्माण के लिए मेरे कोड है:

Socket socket = new Socket(); 
socket.setReuseAddress(true); 
socket.connect(new InetSocketAddress(m_host, m_port)); 

लेकिन मैं अभी भी यह त्रुटि प्राप्त:

java.net.BindException: Address already in use: connect after awhile.

वहाँ किसी अन्य तरीके से मुझे क्या करना कोशिश कर रहा हूँ पूरा करने के लिए है? उदाहरण के लिए: उदाहरण के लिए: 100 सॉकेट खोलें, उन सभी को बंद करें, 200 सॉकेट खोलें, उन्हें बंद करें, 300 खोलें, आदि 2000 या उससे अधिक सॉकेट तक।

किसी भी मदद की सराहना की जाएगी!

+1

क्या यह सर्वर या क्लाइंट है जो अपवाद को फेंकता है? क्या यह लगातार संख्या में कनेक्शन के बाद होता है? –

+1

आपको शायद मशीन की टीसीपी सेटिंग्स को बदलने की जरूरत है, http://docs.alfresco.com/4.0/topic/com.alfresco.enterprise.doc/tasks/alf-win-regedit.html –

उत्तर

15

आप दो मिनट की TIME_WAIT अवधि के भीतर कई आउटबाउंड सॉकेट खोलकर आउटबाउंड बंदरगाहों की जगह को प्रोत्साहित कर रहे हैं। पहला सवाल आपको खुद से पूछना चाहिए क्या यह वास्तव में यथार्थवादी भार परीक्षण का प्रतिनिधित्व करता है? क्या एक वास्तविक ग्राहक वास्तव में ऐसा करने जा रहा है? यदि नहीं, तो आपको बस अपनी परीक्षण पद्धति को संशोधित करने की आवश्यकता है।

बीटीडब्ल्यू SO_LINGER एप्लिकेशन सेकेंड की संख्या है जो डेटा को फ़्लश करने के लिए नज़दीक() के दौरान प्रतीक्षा करेगा। यह सामान्य रूप से शून्य है।पोर्ट बंद होने पर अंतराल जारी होने पर अंतराल TIME_WAIT अंतराल के लिए लटका होगा। यह वही बात नहीं है। समस्या को पैच करने के लिए SO_LINGER विकल्प का दुरुपयोग करना संभव है। हालांकि यह सहकर्मी पर असाधारण व्यवहार भी करेगा और फिर यह एक परीक्षण का उद्देश्य नहीं है।

+0

आप सही हैं कि कोई वास्तविक ग्राहक कई कनेक्शन खोलने वाला नहीं होगा। मेरे आवेदन में, वास्तविक ग्राहक केवल सर्वर के लिए 1 टीसीपी कनेक्शन खुलेंगे। जो मैं करने की कोशिश कर रहा हूं वह वास्तविक ग्राहकों का अनुकरण करता है और मैं जितना संभव हो उतना मशीन पर चलने वाले कई अनुरूपित क्लाइंट रखना चाहता हूं। – bradforj287

+0

आपकी प्रतिक्रिया ने भी मेरी मदद की! :-) मैं यहां कुछ जोड़ना चाहता हूं कि यदि आप setSoLinger() विधि का उपयोग करते हैं, तो यह पहले से जुड़े सहकर्मियों के लिए समस्याएं पैदा करता है और वे कभी-कभी डिस्कनेक्ट भी हो जाते हैं! वास्तव में यह नहीं पता कि इस व्यवहार का कारण क्या है, लेकिन इसे समझने में मुझे 45 मिनट का अच्छा लगा! – M2X

+0

@ एम 2 एक्स SO_LINGER बंद डिफ़ॉल्ट है, जो अब हम सभी के रूप में व्यवहार करने के लिए 'बंद()' का कारण बनता है। यदि आप शून्य पर टाइमआउट के साथ 'चालू' और * सेट करते हैं, तो यह उचित बंद होने के बजाय रीसेट जारी करने के लिए 'बंद()' और 'शटडाउन() 'का कारण बनता है। मैं इसका भी उल्लेख नहीं करना चाहता था क्योंकि यह एक अवांछनीय व्यवहार है। यदि सामान्य टीसीपी/आईपी आवेदन में SO_LINGER के साथ गड़बड़ी करने के लिए कोई वैध कारण हैं तो मुझे अभी तक लगभग तीस वर्षों में उनका सामना करना पड़ेगा। – EJP

-1

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

try/catch में connect कथन को लपेटने का प्रयास करें।

यहाँ कुछ छद्म कोड बता देते हैं कि मैं क्या सोचता काम करता रहेगा:

portNumber = x //where x is the first port number you will try 
numConnections = 200 // or however many connections you want to open 
while(numConnections > 0){ 
    try{ 
     connect(host, portNumber) 
     numConnections-- 
    }catch(){} 
    portNumber++ 
} 

इस कोड को इस तरह के "क्या होता है जब सभी बंदरगाहों उपयोग में हैं?" के रूप में कोने मामलों को कवर नहीं करता

+1

देखें इसका कोई मतलब है। वह एक ऐसी सेवा से कनेक्ट करने की कोशिश कर रहा है जो एक निश्चित बंदरगाह संख्या पर सुन रहा है, कोई भी जिसे बढ़ाया जा सकता है, और उसकी समस्या स्थानीय पोर्ट स्पेस नहीं है, न कि रिमोट पोर्ट स्पेस। – EJP

1

बाइंड() का उपयोग नहीं कर रहा है लेकिन setReuseAddress (सत्य) बस अजीब है, मुझे आशा है कि आप setReuseAddress (और बिंदु) के प्रभावों को समझें। 100-2000 बड़ी संख्या में सॉकेट खोलने के लिए नहीं है, हालांकि जिस सर्वर से आप कनेक्ट करने का प्रयास कर रहे हैं (चूंकि यह एक ही एडीआर/पोर्ट जोड़ी दिखता है), तो उन्हें केवल 50/सामान्य बैकलॉग को छोड़ सकता है।

संपादित करें: यदि आपको एकाधिक सॉकेट जल्दी (ermm पोर्ट स्कैन?) खोलने की आवश्यकता है, तो मैं बहुत दृढ़ता से एनआईओ का उपयोग करने की सलाह देता हूं और कनेक्ट()/finishConnect() + चयनकर्ता। एक ही थ्रेड में 1000 सॉकेट खोलना सिर्फ सादा धीमा है। भूल गए हैं कि आपको अपने कोड में किसी भी तरह से कनेक्ट कनेक्ट() की आवश्यकता हो सकती है।

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