2011-10-04 9 views
8

मैं एक साधारण सॉकेट सर्वर लिखना चाहता हूं, हालांकि मैं इसे लंबवत स्केलेबल बनाना चाहता हूं, उदाहरण के लिए, प्रति कनेक्शन धागा नहीं बनाना या बहुत लंबे समय तक चलने वाले कार्यों को नहीं, जो सभी धागे का उपभोग कर सकते हैं।मैं सी # 4.0 का उपयोग कर स्केलेबल सॉकेट सर्वर कैसे लिखूं?

सर्वर को एक प्रश्न युक्त अनुरोध प्राप्त होता है और मनमाने ढंग से बड़े परिणाम को स्ट्रीम करता है।

मैं कच्चे प्रदर्शन की बजाय सरल कोड पर जोर देने के साथ सी # 4 में उपलब्ध तकनीकों और पुस्तकालयों का उपयोग करके ऐसा करने का बेवकूफ तरीका चाहूंगा।

एक सॉकेट सर्वर स्केलेबल सिस्टम का एक उपयोगी हिस्सा है। यदि आप क्षैतिज पैमाने पर स्केल करना चाहते हैं, तो विभिन्न तकनीकें हैं। यदि आपने कभी सॉकेट सर्वर नहीं बनाया है तो आपको शायद इस प्रश्न का उत्तर देने में सक्षम नहीं होना चाहिए।

उत्तर

15

मैं एक या दो सप्ताह के लिए कुछ इसी तरह काम कर रहा हूं इसलिए उम्मीद है कि मैं थोड़ा सा आपकी मदद कर पाऊंगा।

यदि आपका ध्यान सरल कोड पर है, तो मैं टीसीपी क्लाइंट और टीसीपीलिस्टर कक्षाओं का उपयोग करने की सलाह दूंगा। वे दोनों काम करने के लिए सॉकेट को अधिक आसान बनाते हैं। जबकि वे .NET Framework 1.1 के बाद से मौजूद हैं, वे अपडेट किए गए हैं और अभी भी आपकी सर्वश्रेष्ठ शर्त हैं।

सरल कोड लिखने में .NET Framework 4.0 का उपयोग करने के तरीके के संदर्भ में, कार्य पहली बात है जो ध्यान में आती है। वे एसिंक्रोनस कोड को बहुत कम दर्दनाक बनाते हैं और सी # 5 बाहर आने के बाद आपके कोड को माइग्रेट करना अधिक आसान हो जाएगा (new async and await keywords)।

इसके बजाय tcpListener.BeginAcceptTcpClient(AsyncCallback callback, object state); का उपयोग कर और एक कॉलबैक विधि है जो EndAcceptTcpClient(); कहेंगे और वैकल्पिक रूप से अपने राज्य वस्तु डाली प्रदान करने के

, सी # 4 आप उपयोग करने के लिए बंद किया जाना, lambdas, और कार्य करने के लिए अनुमति देता है: यहाँ कैसे कार्य आपके कोड को आसान बनाने में कर सकते हैं का एक उदाहरण है यह प्रक्रिया बहुत अधिक पठनीय और मापनीय है।

private void AcceptClient(TcpListener tcpListener) 
{ 
    Task<TcpClient> acceptTcpClientTask = Task.Factory.FromAsync<TcpClient>(tcpListener.BeginAcceptTcpClient, tcpListener.EndAcceptTcpClient, tcpListener); 

    // This allows us to accept another connection without a loop. 
    // Because we are within the ThreadPool, this does not cause a stack overflow. 
    acceptTcpClientTask.ContinueWith(task => { OnAcceptConnection(task.Result); AcceptClient(tcpListener); }, TaskContinuationOptions.OnlyOnRanToCompletion); 
} 

private void OnAcceptConnection(TcpClient tcpClient) 
{ 
    string authority = tcpClient.Client.RemoteEndPoint.ToString(); // Format is: IP:PORT 

    // Start a new Task to handle client-server communication 
} 

FromAsync बहुत उपयोगी के रूप में माइक्रोसॉफ्ट कई भार के कि आम अतुल्यकालिक संचालन को सरल बना सकता है प्रदान की गई है: यहाँ एक उदाहरण है। यहाँ एक और उदाहरण है:

private void Read(State state) 
{ 
    // The int return value is the amount of bytes read accessible through the Task's Result property. 
    Task<int> readTask = Task<int>.Factory.FromAsync(state.NetworkStream.BeginRead, state.NetworkStream.EndRead, state.Data, state.BytesRead, state.Data.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent); 

    readTask.ContinueWith(ReadPacket, TaskContinuationOptions.OnlyOnRanToCompletion); 
    readTask.ContinueWith(ReadPacketError, TaskContinuationOptions.OnlyOnFaulted); 
} 

राज्य सिर्फ एक उपयोगकर्ता परिभाषित वर्ग, डेटा (बाइट सरणी) है कि आम तौर पर सिर्फ TcpClient उदाहरण होता है, और शायद बाइट के रूप में अच्छी तरह से पढ़ें।

जैसा कि आप देख सकते हैं, जारी रखें का उपयोग बहुत बोझिल try-catches को बदलने के लिए किया जा सकता है कि अब तक एक आवश्यक बुराई थी।

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

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

आपको याद रखना चाहिए कि थ्रेडपूल एक विशेष कार्य के साथ एक साझा संसाधन है (वास्तव में इसका उपयोग करने से अधिक धागा बनाने के ओवरहेड से बचने के लिए)।क्योंकि यह साझा किया जाता है, यदि आपने धागा का उपयोग किया है, तो कोई अन्य संसाधन नहीं कर सकता है और यह जल्दी से थ्रेड-पूल भुखमरी और deadlock परिदृश्यों का नेतृत्व कर सकता है।

+0

धन्यवाद - यह वही है जो मैं खोज रहा था! –

+5

प्रति थ्रेड का उपयोग करते समय लगभग 1 मिलियन कनेक्शन कैसे? – Shift

+0

फिर आपको थ्रेड पूल धागे का सही ढंग से उपयोग करना चाहिए। – vtortola

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