2013-02-25 59 views
8

का पता लगाने के मैं दो सरल अनुप्रयोगों:C# टीसीपी डिस्कनेक्ट

  • एक सर्वर अनुप्रयोग है कि एक ग्राहक से कनेक्ट करने के लिए एक विशिष्ट TCP पोर्ट पर इंतजार कर रहा है। फिर वह जो कहता है उसे सुनता है, कुछ प्रतिक्रिया वापस भेजता है और उस ग्राहक को अस्वीकार करता है।

  • सर्वर एप्लिकेशन से कनेक्ट होने वाला एक फॉर्म एप्लिकेशन, फिर कुछ कहता है, फिर प्रतिक्रिया से प्रतीक्षा करें और सर्वर से डिस्कनेक्ट करें, फिर फॉर्म में फीडबैक दिखाएं।

हालांकि सर्वर अनुप्रयोग ठीक से व्यवहार करने लगता है (मैं इसे टेलनेट के साथ परीक्षण किया है और मैं प्रतिक्रिया को देखते हैं और मैं डिस्कनेक्ट प्रतिक्रिया के बाद सीधे होने वाली देखें), प्रपत्र आवेदन तथापि सूचना के लिए प्रतीत नहीं होता सर्वर से डिस्कनेक्ट करें। (TcpClient.Connected सर्वर से डिस्कनेक्ट होने के बाद भी सत्य रहना प्रतीत होता है)

मेरा प्रश्न है: TcpClient.Connected क्यों रह रहा है और यह कैसे पता चलेगा कि सर्वर डिस्कनेक्ट हो गया है या नहीं?

फार्म आवेदन:

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace Sender 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void sendButton_Click(object sender, EventArgs e) 
     { 
      TcpClient tcpClient = new TcpClient(); 
      tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 81); 
      responseLabel.Text = "waiting for response..."; 
      responseLabel.Invalidate(); 

      // write request 
      NetworkStream networkStream = tcpClient.GetStream(); 
      byte[] buffer = (new ASCIIEncoding()).GetBytes("Hello World! "); 
      networkStream.Write(buffer, 0, buffer.Length); 
      networkStream.Flush(); 

      // read response 
      Thread readThread = new Thread(new ParameterizedThreadStart(ReadResponse)); 
      readThread.Start(tcpClient); 
     } 

     void ReadResponse(object arg) 
     { 
      TcpClient tcpClient = (TcpClient)arg; 
      StringBuilder stringBuilder = new StringBuilder(); 
      NetworkStream networkStream = tcpClient.GetStream(); 
      bool timeout = false; 
      DateTime lastActivity = DateTime.Now; 
      while (tcpClient.Connected && !timeout) 
      { 
       if (networkStream.DataAvailable) 
       { 
        lastActivity = DateTime.Now; 
        while (networkStream.DataAvailable) 
        { 
         byte[] incomingBuffer = new byte[1024]; 
         networkStream.Read(incomingBuffer, 0, 1024); 
         char[] receivedChars = new char[1024]; 
         (new ASCIIEncoding()).GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0); 
         stringBuilder.Append(receivedChars); 
        } 
       } 
       else 
       { 
        if (DateTime.Now > lastActivity.AddSeconds(60)) 
         timeout = true; 
       } 
       System.Threading.Thread.Sleep(50); 
      } 
      Invoke((MethodInvoker)delegate 
      { 
       responseLabel.Text = "Response from Listener:\n" + stringBuilder.ToString(); 
       responseLabel.Invalidate(); 
      }); 

      if (timeout) 
      { 
       Console.Write("A timeout occured\n"); 
       networkStream.Close(); 
       tcpClient.Close(); 
      } 
     } 

    } 
} 

सर्वर आवेदन:

using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System; 
using System.Threading; 

namespace Listener 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var tcpListener = new TcpListener(IPAddress.Any, 81); 
      tcpListener.Start(); 
      Thread clientThread = new Thread(new ParameterizedThreadStart(Listen)); 
      clientThread.Start(tcpListener); 
     } 

     static void Listen(object arg) 
     { 
      TcpListener tcpListener = (TcpListener)arg; 
      while (true) 
      { 
       TcpClient tcpClient = tcpListener.AcceptTcpClient(); 
       Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient)); 
       clientThread.Start(tcpClient); 
      } 
     } 

     static void HandleClient(object arg) 
     { 
      TcpClient tcpClient = (TcpClient)arg; 
      StringBuilder stringBuilder = new StringBuilder(); 
      ASCIIEncoding encoder = new ASCIIEncoding(); 
      DateTime lastActivity = DateTime.Now; 

      // read request 
      NetworkStream networkStream = tcpClient.GetStream(); 
      int timeout = 5; // gives client some time to send data after connecting 
      while (DateTime.Now < lastActivity.AddSeconds(timeout) && stringBuilder.Length==0) 
      { 
       if (!networkStream.DataAvailable) 
       { 
        System.Threading.Thread.Sleep(50); 
       } 
       else 
       { 
        while (networkStream.DataAvailable) 
        { 
         lastActivity = DateTime.Now; 
         byte[] incomingBuffer = new byte[1024]; 
         networkStream.Read(incomingBuffer, 0, 1024); 
         char[] receivedChars = new char[1024]; 
         encoder.GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0); 
         stringBuilder.Append(receivedChars); 
        } 
       } 
      } 
      string request = stringBuilder.ToString(); 

      // write response 
      string response = "The listener just received: " + request; 
      byte[] outgoingBuffer = encoder.GetBytes(response); 
      networkStream.Write(outgoingBuffer, 0, outgoingBuffer.Length); 
      networkStream.Flush(); 

      networkStream.Close(); 
      tcpClient.Close(); 
     } 
    } 

} 

उत्तर

9

TcpClient/NetworkStream अधिसूचित नहीं प्राप्त करता है जब कनेक्शन बंद कर दिया है

यहाँ मेरा पूरा कोड है। स्ट्रीम में लिखते समय आपके लिए उपलब्ध एकमात्र विकल्प अपवादों को पकड़ना है।

कुछ साल पहले हम टीसीपी क्लाइंट के बजाय सॉकेट का उपयोग करने के लिए चले गए। टीसीपीक्लिएंट की तुलना में सॉकेट अधिक उपयोग योग्य है।

आप उपयोग कर सकते हैं कि

पोल उन्हें

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.poll.aspx

तुम भी लिखें खुद के परिणाम पर एक चेक कर सकते हैं में से एक है तरीकों की एक जोड़ी रहे हैं। यह आपको वास्तव में लिखित बाइट्स की संख्या देता है।

कनेक्टेड संपत्ति केवल अंतिम ऑपरेशन में ही राज्य को दर्शाती है। इसके दस्तावेज में कहा गया है "कनेक्टेड संपत्ति का मूल्य सबसे हालिया ऑपरेशन के रूप में कनेक्शन की स्थिति को दर्शाता है। अगर आपको कनेक्शन की वर्तमान स्थिति निर्धारित करने की आवश्यकता है, तो एक गैर-अवरुद्ध, शून्य-बाइट भेजें कॉल करें। अगर कॉल सफलतापूर्वक लौटता है या WAEWOULDBLOCK त्रुटि कोड (10035) फेंकता है, तो सॉकेट अभी भी जुड़ा हुआ है, अन्यथा, सॉकेट अब कनेक्ट नहीं है। "

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.connected.aspx

+0

सहमत हैं, सॉकेट – XikiryoX

+0

का उपयोग करने के लिए एक बेहतर विकल्प होगा नेटवर्कस्ट्रीम स्वयं सॉकेट का उपयोग करता है (हालांकि यह सार्वजनिक संपत्ति नहीं है)। मैं इसका उपयोग कैसे कर पाऊंगा? दूसरे शब्दों में: अगर मैं सॉकेट का उपयोग कर रहा था, तो क्लाइंट डिस्कनेक्ट होने पर मैं कैसे जानूंगा? –

+0

पोल पर एक नज़र डालें .. मैं मानता हूं कि नेटवर्क स्ट्रीम और टीसीपी क्लाइंट सॉकेट का उपयोग करता है लेकिन वे एक उच्च स्तरीय इंटरफेस प्रदान करते हैं .. सॉकेट हालांकि सॉकेट है .. आप जो देखते हैं वह आपको मिलता है :) –

0
networkStream.DataAvailable 

यह गुण आपको सूचित नहीं करता सॉकेट सर्वर साइड पर बंद कर दिया है।

आपकी स्थिति में, आप या तो "रखरखाव" फ़ंक्शन को कार्यान्वित कर सकते हैं जहां आप प्रत्येक टी मिनट/सेकंड कनेक्शन को पराग करते हैं, या जब भी आप सॉकेट से पढ़ने या लिखने का प्रयास करते हैं तो बहुत सारे प्रयास/कैच जोड़ते हैं। जब मैं टीसीपी का उपयोग करता हूं, तो मुझे बस एक रिकॉन्क() विधि शामिल होती है जो प्रत्येक पकड़ विवरण में जाती है।