2015-09-04 6 views
6
का उपयोग करना चाहिए

मेरा मानना ​​है कि बंद अनुक्रम (वर्णित here के रूप में) इस प्रकार है:सॉकेट शटडाउन: जब मैं SocketShutdown.Both

Socket Shutdown sequence

MSDN documentation (टिप्पणी अनुभाग) पढ़ता है:

कनेक्शन-उन्मुख Socket का उपयोग करते समय, Socket को बंद करने से पहले हमेशा Shutdown विधि पर कॉल करें। यह सुनिश्चित करता है कि कनेक्ट होने से पहले कनेक्ट किए गए सॉकेट पर सभी डेटा भेज और प्राप्त किया जाता है।

ऐसा लगता है कि अगर मैं Shutdown(SocketShutdown.Both) का उपयोग करता हूं, तो अभी तक प्राप्त कोई भी डेटा अभी भी उपभोग नहीं किया जा सकता है। इसका परीक्षण करने के लिए:

  • मैं लगातार ग्राहक को डेटा भेजता हूं (Send के माध्यम से एक अलग थ्रेड में)।
  • ग्राहक ने Shutdown(SocketShutdown.Both) निष्पादित किया।
  • BeginReceive सर्वर निष्पादन पर कॉलबैक, हालांकि, EndReceive अपवाद फेंकता है: रिमोट होस्ट द्वारा एक मौजूदा कनेक्शन जबरन बंद कर दिया गया था। इसका मतलब है कि मैं 0 वापसी मूल्य प्राप्त करने में असमर्थ हूं और बदले में Shutdown पर कॉल कर सकता हूं।

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

  • ग्राहक सर्वर से कनेक्ट होता है।
  • ग्राहक Shutdown(SocketShutdown.Both) निष्पादित करता है।
  • सर्वर को शटडाउन पावती प्राप्त होती है और प्रतिक्रिया में कुछ डेटा भेजती है। सर्वर Shutdown निष्पादित करता है।
  • क्लाइंट सर्वर से डेटा प्राप्त करता है लेकिन अगले BeginReceive अनुमति नहीं है: एक अनुरोध डेटा भेजने या प्राप्त करने के लिए अस्वीकृत हो गया क्योंकि सॉकेट पहले से ही पिछले एक बंद कॉल के साथ उस दिशा में बंद कर दिया गया था

में इस परिदृश्य में, मुझे अभी भी 0EndReceive से Close सॉकेट से वापसी मूल्य की उम्मीद थी। क्या इसका मतलब है कि मुझे इसके बजाय Shutdown(SocketShutdown.Send) का उपयोग करना चाहिए? यदि हां, तो Shutdown(SocketShutdown.Both) का उपयोग कब करना चाहिए?

पहला प्रयोग से कोड:

private TcpListener SocketListener { get; set; } 
private Socket ConnectedClient { get; set; } 
private bool serverShutdownRequested; 
private object shutdownLock = new object(); 

private struct SocketState 
{ 
    public Socket socket; 
    public byte[] bytes; 
} 

private void ProcessIncoming(IAsyncResult ar) 
{ 
    var state = (SocketState)ar.AsyncState; 
    // Exception thrown here when client executes Shutdown: 
    var dataRead = state.socket.EndReceive(ar); 
    if (dataRead > 0) 
    { 
    state.socket.BeginReceive(state.bytes, 0, state.bytes.Length, SocketFlags.None, ProcessIncoming, state); 
    } 
    else 
    { 
    lock (shutdownLock) 
    { 
     serverShutdownRequested = true; 
     state.socket.Shutdown(SocketShutdown.Both); 
     state.socket.Close(); 
     state.socket.Dispose(); 
    } 
    } 
} 

private void Spam() 
{ 
    int i = 0; 
    while (true) 
    { 
    lock (shutdownLock) 
    { 
     if (!serverShutdownRequested) 
     { 
     try { ConnectedClient.Send(Encoding.Default.GetBytes(i.ToString())); } 
     catch { break; } 
     ++i; 
     } 
     else { break; } 
    } 
    } 
} 

private void Listen() 
{ 
    while (true) 
    { 
    ConnectedClient = SocketListener.AcceptSocket(); 
    var data = new SocketState(); 
    data.bytes = new byte[1024]; 
    data.socket = ConnectedClient; 
    ConnectedClient.BeginReceive(data.bytes, 0, data.bytes.Length, SocketFlags.None, ProcessIncoming, data); 
    serverShutdownRequested = false; 
    new Thread(Spam).Start(); 
    } 
} 

public ServerForm() 
{ 
    InitializeComponent(); 
    var hostEntry = Dns.GetHostEntry("localhost"); 
    var endPoint = new IPEndPoint(hostEntry.AddressList[0], 11000); 
    SocketListener = new TcpListener(endPoint); 
    SocketListener.Start(); 
    new Thread(Listen).Start(); 
} 
+0

'भेजें' शट डाउन अनुक्रम के दौरान '0' भी देता है। यदि मैं इसे 'स्पैम' विधि में सेट करने से पहले, * सर्वर * को अपडेट करने के लिए अद्यतन करता हूं, तो 'EndReceive' अभी भी एक अपवाद फेंकता है। मुझे संदेह है कि यह सब होता है क्योंकि 'CLOSE_WAIT' सॉकेट स्थिति किसी भी तरह से छोड़ी जाती है। – Pooven

उत्तर

1

यह सूचित करते हैं कि अगर मैं शटडाउन (SocketShutdown.Both) का उपयोग करें, किसी भी डेटा को अभी तक प्राप्त नहीं हुआ है, अभी भी सेवन किया जा सकता है लगता है

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

कोई मौजूदा कनेक्शन बलपूर्वक दूरस्थ होस्ट

यह ऐसा नहीं होना चाहिए द्वारा बंद कर दिया गया था। पोस्ट कोड

क्या इसका मतलब यह है कि मुझे इसके बजाय शटडाउन (सॉकेटशूटडाउन.एंड) का उपयोग करना चाहिए?

यदि आप प्राप्त करना जारी रखना चाहते हैं तो आप प्राप्त क्यों बंद कर रहे हैं? बस ऐसा मत करो। केवल भेजना बंद करें।

यदि ऐसा है, तो किसी को शटडाउन (सॉकेटशूटडाउन.बॉथ) का उपयोग कब करना चाहिए?

जब आप न तो प्राप्त करना और न ही भेजना चाहते हैं। क्या आप विस्तार से बता सकते हैं कि यह आपके लिए क्यों स्पष्ट नहीं है? शायद एक गलतफहमी है या मुझे सवाल नहीं मिला है।

+0

उत्तर के लिए धन्यवाद। ** 1। ** यदि डेटा चला गया है तो 'शटडाउन' और 'बंद' कैसे भिन्न है? दस्तावेज़ीकरण का अर्थ क्या है: 'यह सुनिश्चित करता है कि सभी डेटा भेजा और प्राप्त किया गया है'? ** 2। ** मैंने केवल सर्वर कोड पोस्ट किया है; क्या यह पर्याप्त है? ** 3। ** 'शट डाउन नहीं (सॉकेटशूटडाउन.एंड) 'मतलब है कि मैं आने वाले डेटा की अनुमति दे रहा हूं? ** 4। ** यदि मैं न तो प्राप्त करना या भेजना चाहता हूं, तो मुझे 'बंद करें 'के बजाय' शट डाउन' क्यों करना चाहिए? आइटम 1 से संबंधित, मैं सही सॉकेट डिस्कनेक्शन अनुक्रम और इसे करने के नतीजे समझने की कोशिश कर रहा हूं। – Pooven

+0

1. बंद त्रुटियों की रिपोर्ट नहीं करता है। आम तौर पर, आपको बंद होने से पहले शट डाउन कॉल करना चाहिए ताकि त्रुटियों की सूचना दी जा सके। 2. मुझे भी ग्राहक की जरूरत है। सर्वर ठीक दिखता है। 3. हां। 4. देखें (1) .; सही अनुक्रम शटडाउन (दोनों) है; निपटाने। कभी नजदीकी कॉल करें। – usr

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