2014-01-08 78 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