मेरा मानना है कि बंद अनुक्रम (वर्णित here के रूप में) इस प्रकार है:सॉकेट शटडाउन: जब मैं SocketShutdown.Both
MSDN documentation (टिप्पणी अनुभाग) पढ़ता है:
कनेक्शन-उन्मुख
Socket
का उपयोग करते समय,Socket
को बंद करने से पहले हमेशाShutdown
विधि पर कॉल करें। यह सुनिश्चित करता है कि कनेक्ट होने से पहले कनेक्ट किए गए सॉकेट पर सभी डेटा भेज और प्राप्त किया जाता है।
ऐसा लगता है कि अगर मैं Shutdown(SocketShutdown.Both)
का उपयोग करता हूं, तो अभी तक प्राप्त कोई भी डेटा अभी भी उपभोग नहीं किया जा सकता है। इसका परीक्षण करने के लिए:
- मैं लगातार ग्राहक को डेटा भेजता हूं (
Send
के माध्यम से एक अलग थ्रेड में)। - ग्राहक ने
Shutdown(SocketShutdown.Both)
निष्पादित किया। BeginReceive
सर्वर निष्पादन पर कॉलबैक, हालांकि,EndReceive
अपवाद फेंकता है: रिमोट होस्ट द्वारा एक मौजूदा कनेक्शन जबरन बंद कर दिया गया था। इसका मतलब है कि मैं0
वापसी मूल्य प्राप्त करने में असमर्थ हूं और बदले मेंShutdown
पर कॉल कर सकता हूं।
जैसा कि अनुरोध किया गया है, मैंने नीचे सर्वर साइड कोड पोस्ट किया है (यह विंडोज फॉर्म में लपेटा गया है और इसे केवल एक प्रयोग के रूप में बनाया गया था)। मेरे परीक्षण परिदृश्य में मैंने CLOSE_WAIT
राज्य TCPView में नहीं देखा क्योंकि मैंने सामान्य रूप से निरंतर डेटा भेजने के बिना किया था। इसलिए संभावित रूप से मैंने कुछ गलत किया है और मैं परिणामों को गलत तरीके से बाधित कर रहा हूं। एक और प्रयोग में:
- ग्राहक सर्वर से कनेक्ट होता है।
- ग्राहक
Shutdown(SocketShutdown.Both)
निष्पादित करता है। - सर्वर को शटडाउन पावती प्राप्त होती है और प्रतिक्रिया में कुछ डेटा भेजती है। सर्वर
Shutdown
निष्पादित करता है। - क्लाइंट सर्वर से डेटा प्राप्त करता है लेकिन अगले
BeginReceive
अनुमति नहीं है: एक अनुरोध डेटा भेजने या प्राप्त करने के लिए अस्वीकृत हो गया क्योंकि सॉकेट पहले से ही पिछले एक बंद कॉल के साथ उस दिशा में बंद कर दिया गया था
में इस परिदृश्य में, मुझे अभी भी 0
EndReceive
से 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' भी देता है। यदि मैं इसे 'स्पैम' विधि में सेट करने से पहले, * सर्वर * को अपडेट करने के लिए अद्यतन करता हूं, तो 'EndReceive' अभी भी एक अपवाद फेंकता है। मुझे संदेह है कि यह सब होता है क्योंकि 'CLOSE_WAIT' सॉकेट स्थिति किसी भी तरह से छोड़ी जाती है। – Pooven