2014-01-08 106 views
0

Im連接到Socket服務器以發送和接收消息。一切工作正常,因爲消息進出,但每隔一段時間它就會失去聯繫。我試圖捕捉異常並重新連接到服務器。 連接丟失時的第一個例外:重新連接TCPClient拋出異常

System.IO.IOException:無法從傳輸連接讀取數據:建立的連接被主機中的軟件中止。 ---> System.Net.Sockets.SocketException:一個建立的連接是由軟件在主機 在System.Net.Sockets.Socket.Receive中止(字節[]緩衝液,的Int32偏移的Int32大小,的SocketFlags的SocketFlags) 在System.Net.Sockets.NetworkStream.Read(字節[]緩衝液,的Int32偏移的Int32大小)

,然後當它試圖重新連接:

System.ObjectDisposedException:無法訪問已釋放的對象。 對象名稱:'System.Net.Sockets.NetworkStream'。 at System.Net.Sockets.NetworkStream.Read(Byte [] buffer,Int32 offset,Int32 size)

我的問題是我做錯了什麼?什麼是重新連接到服務器的最佳解決方案? 我的代碼看起來像這樣:

class Test 
     { 
      private TcpClient myTcpClient; 
      private NetworkStream myStream; 
      private string host = xxx.xxx.xxx; 
      private int port = 8888; 
      private string streaming = ""; 

     public void Listen() 
     { 
      this.myTcpClient = new TcpClient(host, port); 
      this.myStream = this.myTcpClient.GetStream(); 
      Listener(); 
     } 

     private void Listener() 
     { 
      try 
      { 
       while (true) 
       { 
        byte[] numResponse = new byte[8192]; 
        int x = this.myStream.Read(numResponse, 0, numResponse.Length); 
        Decrypt(numResponse, 0, x); 
        string stream = Encoding.UTF8.GetString(numResponse); 
        this.streaming = string.Concat(this.streaming, stream); 
       } 
      } 
      catch(Excpetion ex) 
      { 
       // write ex.ToString() to TextFile 
       this.myTcpClient = new TcpClient(host, port); 
       this.myStream = this.myTcpClient.GetStream(); 
       Listener(); 
      } 
     } 
    } 
+0

不相關,但您沒有使用myStream.Read的返回值。這總是一個錯誤。使用StreamReader從NetworkStream讀取。你的Unicode解碼也被破壞,因爲數據包可能被任意分割。 – usr

回答

1

我覺得你的異常所引起,因爲你正在做的catch語句內重新初始化。

雖然抓內部網絡流仍然是開放的。所以當你使用相同的端口創建一個新的TCP客戶端時,我猜測它正在使用與之前相同的網絡流,該流被鎖定在試圖讀取的位置。

漁獲裏面,你可以嘗試

this.myTcpClient.Close(); 
this.myTcpClient.Dispose(); 
this.myTcpClient = new TcpClient(host, port); 
this.myStream = this.myTcpClient.GetStream(); 

可能的工作。但我建議不要在catch中這樣做,因爲你可能會導致另一個異常。我會說,嘗試閱讀一些例子,因爲這個代碼還有其他問題,如其他答案中提到的其他問題。

0

你不應該在while(true)循環中讀入。更好地檢查myStream.Read是否返回0字節或TCP相關異常發生,在這種情況下,連接將被關閉。我認爲,您需要處理資源並重新連接。

在這裏你能夠找到安全的讀書方法 - http://www.yoda.arachsys.com/csharp/readbinary.html

-1

下面是一些代碼,可以幫助

// State object for receiving data from remote device. 
public class StateObject 
{ 
    /// <summary> 
    /// Client socket. 
    /// </summary> 
    public Socket workSocket = null; 

    /// <summary> 
    /// Size of receive buffer. 
    /// </summary> 
    public const int BufferSize = 256; 

    /// <summary> 
    /// Receive buffer. 
    /// </summary> 
    public byte[] buffer = new byte[BufferSize]; 

    /// <summary> 
    /// Received data string. 
    /// </summary> 
    public StringBuilder sb = new StringBuilder(); 
} 

public class AsynchronousClient 
{ 
    // The port number for the remote device. 
    private const int _port = xxxx; 
    private const string _address = "xx.xx.xx.xx"; 

    // ManualResetEvent instances signal completion. 
    private static ManualResetEvent _connectDone = new ManualResetEvent(false); 
    private static ManualResetEvent _sendDone = new ManualResetEvent(false); 
    private static ManualResetEvent _receiveDone = new ManualResetEvent(false); 

    private static string _response = string.Empty; 

    public static void StartClient(string data) 
    { 
     // Connect to a remote device. 
     try 
     { 
      var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

      // Connect to the remote endpoint. 
      client.BeginConnect(_address, _port, ConnectCallback, client); 
      _connectDone.WaitOne(); 

      // Send test data to the remote device. 
      //Console.WriteLine("Sending data : {0}", data); 
      Send(client, "US\r\n"); 
      _sendDone.WaitOne(); 


      Thread.Sleep(1000); 
      Send(client, data); 
      _sendDone.WaitOne(); 


      // Receive the response from the remote device.     
      Receive(client); 
      _receiveDone.WaitOne(); 

      // Write the response to the console. 
      //Console.WriteLine("Response received : {0}", _response); 

      // Release the socket. 
      client.Shutdown(SocketShutdown.Both); 
      client.Close(); 

     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void ConnectCallback(IAsyncResult ar) 
    { 
     try 
     { 
      // Retrieve the socket from the state object. 
      var client = (Socket)ar.AsyncState; 

      // Complete the connection. 
      client.EndConnect(ar); 

      Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString()); 

      // Signal that the connection has been made. 
      _connectDone.Set(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void Receive(Socket client) 
    { 
     try 
     { 
      // Create the state object. 
      var state = new StateObject(); 
      state.workSocket = client; 

      // Begin receiving the data from the remote device. 
      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void ReceiveCallback(IAsyncResult ar) 
    { 
     try 
     { 
      // Retrieve the state object and the client socket 
      // from the asynchronous state object. 
      var state = (StateObject)ar.AsyncState; 
      var client = state.workSocket; 

      int bytesRead = client.EndReceive(ar); 
      if (bytesRead > 0) 
      { 
       state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
       client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state); 
      } 
      else 
      { 
       // All the data has arrived; put it in response. 
       if (state.sb.Length > 1) _response = state.sb.ToString();      
       _receiveDone.Set(); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void Send(Socket client, String data) 
    {    
     var byteData = Encoding.ASCII.GetBytes(data); 
     client.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, client); 
    } 

    private static void SendCallback(IAsyncResult ar) 
    { 
     try 
     { 
      var client = (Socket)ar.AsyncState; 

      var bytesSent = client.EndSend(ar);     
      Console.WriteLine("Sent {0} bytes to server.", bytesSent);     
      _sendDone.Set(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
} 
+0

此代碼是基於套接字的,而作者試圖使用TcpClient。 – realnero

+0

same..isn't tcpclient只是套接字的包裝? – wakthar

+0

它是一個包裝。但作者試圖找出他的代碼中的問題,而不是要求提供新的解決方案 – realnero