2010-11-23 15 views
6

मैं सी # में एक एप्लीकेशन लिख रहा हूं जिसमें आने वाले कनेक्शन को संभालने की आवश्यकता है और मैंने कभी सर्वर साइड प्रोग्रामिंग नहीं की है। यह मुझे निम्नलिखित प्रश्नों पर ले जाता है:सॉकेट के लिए सुनने और बैकलॉग के बारे में प्रश्न

  • उच्च बैकलॉग/कम बैकलॉग के पेशेवरों और विपक्ष? हमें बैकलॉग को बड़ी संख्या में क्यों नहीं सेट करना चाहिए?
  • अगर मैं सॉकेट कहता हूं। लिस्टेन (10), 10 स्वीकार करने के बाद() क्या मुझे फिर से सुनो() कॉल करना होगा? या मुझे हर स्वीकृति() के बाद सुनो() को कॉल करना है?
  • यदि मैं अपना बैकलॉग 0 पर सेट करता हूं और hypothetically दो लोग एक ही समय में मेरे सर्वर से कनेक्ट करना चाहते हैं, तो क्या होगा? (मैं एक पाश में Socket.Select बोल रहा हूँ और सुन सॉकेट की पठनीयता जाँच, के बाद मैं संभाल पहले कनेक्शन दूसरा कनेक्शन अगर मैं (सुनो) फिर से बुलाया अगले चरण पर सफल हो सकता है?)

धन्यवाद अग्रिम रूप से।

उत्तर

13

सुनने बैकलॉग, as Pieter said, एक कतार जो ऑपरेटिंग सिस्टम द्वारा प्रयोग किया जाता है कनेक्शन टीसीपी ढेर द्वारा स्वीकार किया गया है, लेकिन नहीं है, फिर भी, अपने कार्यक्रम से स्टोर करने के लिए है। संकल्पनात्मक रूप से, जब कोई क्लाइंट इसे इस कतार में तब तक जोड़ता है जब तक कि आपके Accept() कोड इसे हटा देता है और इसे आपके प्रोग्राम पर सौंप देता है।

इस प्रकार, सुनो बैकलॉग एक ट्यूनिंग पैरामीटर है जिसका उपयोग आपके सर्वर को समवर्ती कनेक्शन प्रयासों में चोटियों को संभालने में मदद के लिए किया जा सकता है। ध्यान दें कि यह समवर्ती कनेक्शन प्रयासों में चोटियों से संबंधित है और आपके सर्वर द्वारा बनाए जा सकने वाले समवर्ती कनेक्शन की अधिकतम संख्या से संबंधित नहीं है। उदाहरण के लिए, यदि आपके पास एक सर्वर है जो प्रति सेकेंड 10 नए कनेक्शन प्राप्त करता है तो यह संभावना नहीं है कि श्रवण बैकलॉग को ट्यून करने से कोई असर पड़ेगा, भले ही ये कनेक्शन लंबे समय तक रहते हों और आपका सर्वर 10,000 समवर्ती कनेक्शन का समर्थन कर रहा है (मान लें कि आपका सर्वर अधिकतम नहीं है मौजूदा कनेक्शन की सेवा करने वाले सीपीयू को बाहर निकालें!)।हालांकि, यदि सर्वर को प्रति सेकंड 1000 नए कनेक्शन स्वीकार करते समय कभी-कभी छोटी अवधि का अनुभव होता है तो आप शायद कुछ कनेक्शन को एक बड़ी कतार प्रदान करने के लिए सुनो बैकलॉग को ट्यून करके अस्वीकार कर सकते हैं और इसलिए प्रत्येक सर्वर को Accept() पर कॉल करने के लिए अपने सर्वर को अधिक समय दें कनेक्शन।

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

व्यक्तिगत रूप से मैं सुनवाई बैकलॉग कुछ करता हूं जिसे कॉन्फ़िगरेशन फ़ाइल के माध्यम से बाहरी रूप से ट्यून किया जा सकता है।

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

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

+0

हाय, मैं परीक्षण लिखने की कोशिश कर रहा हूं ... और कोड नहीं है ... यह स्पष्ट कर रहा है कि समस्या क्या है ... मैं 10 000 क्लाइंट अनुरोध से लूपिंग कर रहा हूं ... प्रत्येक कनेक्शन अपना स्वयं का टीसीपी बनाता है कनेक्शन। मैंने बैकलॉग को 20 000 पर सेट किया है। श्रोता कनेक्शन को असीमित रूप से स्वीकार कर रहा है और उन्हें अपने स्वयं के धागे में डाल रहा है। मैंने 5 सेकंड काम करने के लिए श्रोता पर प्रत्येक स्वीकृत कनेक्शन को बताया है। लगभग तुरंत मुझे क्लाइंट द्वारा मना कर दिया जा रहा है ... मुझे पता है कि यह असली दुनिया परीक्षण नहीं है ... मैं बस सभी सीमाओं को समझने की कोशिश कर रहा हूं ... क्या आप मुझे समझने में मदद करने में सहायता कर सकते हैं .. – Seabizkit

+0

1) आप ' एक मौजूदा उत्तर पर एक अस्पष्ट टिप्पणी जोड़ने के बजाय एक प्रश्न लिखने से बेहतर होगा। 2) "थ्रेड प्रति कनेक्शन" मॉडल का उपयोग करके 10,000 तक स्केलिंग आदर्श नहीं है। 3) इस प्रकार का परीक्षण विभिन्न सिस्टम संसाधन सीमाओं में चलाया जा सकता है, इस पर निर्भर करता है कि यह कैसे संरचित है (TIME_WAIT) उनमें से एक है। 4) 20,000 का बैकलॉग सिर्फ "20,000 कनेक्शन लंबित होने की अनुमति देता है" यह प्रभावित नहीं करता है कि कितने सक्रिय कनेक्शन संभव हैं, 20,000 इसके लिए बहुत बड़ी संख्या है और ओएस की तुलना में बड़ा हो सकता है ... 5) ऐसी कई चीजें हैं जो आप गलत कर सकते हैं, मुझे कोड देखना होगा –

2

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

यह क्लाइंट वास्तव में सर्वर से कनेक्ट होने के समय और Accept या EndAccept क्लाइंट के बीच के समय से संबंधित है।

यदि ग्राहक को स्वीकार करना काफी समय लगता है, तो यह संभव है कि बैकलॉग पूर्ण हो जाए और नए ग्राहक कनेक्शन तब तक खारिज कर दिए जाएंगे जब तक आपके पास कतार से ग्राहकों को संसाधित करने का समय न हो।

आपके प्रश्नों के संबंध में:

  1. मुझे लगता है कि के बारे में जानकारी नहीं है। यदि डिफ़ॉल्ट संख्या कोई समस्या नहीं उत्पन्न करती है (कोई अस्वीकृत क्लाइंट कनेक्शन नहीं) इसे अपने डिफ़ॉल्ट पर छोड़ दें। यदि आप नए क्लाइंट कनेक्ट करना चाहते हैं तो आपको कई त्रुटियां दिखाई देती हैं, तो संख्या बढ़ाएं। हालांकि, ऐसा शायद इसलिए होगा क्योंकि आप एक नए ग्राहक को स्वीकार करने में बहुत अधिक समय लेते हैं। बैकलॉग बढ़ाने से पहले आपको उस मुद्दे को हल करना चाहिए;

  2. नहीं, यह सिस्टम द्वारा संभाला जाता है। ग्राहकों को स्वीकार करने का सामान्य तंत्र इसका ख्याल रखता है;

  3. मेरी पिछली स्पष्टीकरण देखें।

2

इस कार्यक्रम को आजमाएं और आप देखेंगे कि बैकलॉग क्या अच्छा है।

using System; 
using System.Net; 
using System.Net.Sockets; 

/* 
    This program creates TCP server socket. Then a large number of clients tries to connect it. 
    Server counts connected clients. The number of successfully connected clients depends on the BACKLOG_SIZE parameter. 
*/ 


namespace BacklogTest 
{ 
    class Program 
    { 
     private const int BACKLOG_SIZE = 0; //<<< Change this to 10, 20 ... 100 and see what happens!!!! 
     private const int PORT = 12345; 
     private const int maxClients = 100; 

     private static Socket serverSocket; 
     private static int clientCounter = 0; 

     private static void AcceptCallback(IAsyncResult ar) 
     { 
      // Get the socket that handles the client request 
      Socket listener = (Socket) ar.AsyncState; 
      listener.EndAccept(ar); 
      ++clientCounter; 
      Console.WriteLine("Connected clients count: " + clientCounter.ToString() + " of " + maxClients.ToString()); 

      // do other some work 
      for (int i = 0; i < 100000; ++i) 
      { 
      } 

      listener.BeginAccept(AcceptCallback, listener); 
     } 

     private static void StartServer() 
     { 
      // Establish the locel endpoint for the socket 
      IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, PORT); 

      // Create a TCP/IP socket 
      serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

      // Bind the socket to the local endpoint and listen 
      serverSocket.Bind(localEndPoint); 
      serverSocket.Listen(BACKLOG_SIZE); 
      serverSocket.BeginAccept(AcceptCallback, serverSocket); 
     } 

     static void Main(string[] args) 
     { 
      StartServer(); 

      // Clients connect to the server. 
      for (int i = 0; i < 100; ++i) 
      { 
       IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); 
       IPEndPoint remoteEP = new IPEndPoint(ipAddress, PORT); 

       // Create a TCP/IP socket and connect to the server 
       Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
       client.BeginConnect(remoteEP, null, null); 
      } 

      Console.ReadKey(); 
     } 
    } 
} 
संबंधित मुद्दे