重新连接TCPClient会引发异常

时间:2014-01-08 14:58:12

标签: c# .net wpf sockets tcp

我连接到套接字服务器以发送和接收消息。当消息进出时,一切都很好,但每隔一段时间就会失去联系。我试图抓住异常并重新连接到服务器。 它失去连接时的第一个例外:

System.IO.IOException:无法从传输连接读取数据:已建立的连接已被主机中的软件中止。 ---> System.Net.Sockets.SocketException:已建立的连接已被主机中的软件中止    在System.Net.Sockets.Socket.Receive(Byte []缓冲区,Int32偏移量,Int32大小,SocketFlags socketFlags)    在System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)

然后当它尝试重新连接时:

System.ObjectDisposedException:无法访问已处置的对象。 对象名:'System.Net.Sockets.NetworkStream'。    在System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)

我的问题是我做错了什么?什么是重新连接到服务器的最佳解决方案? 我的代码看起来像这样:

  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();
            }
        }
    }

3 个答案:

答案 0 :(得分:1)

我认为你的异常是由于你在catch语句中进行重新初始化而引起的。

在捕获内部时,网络流仍处于打开状态。因此,当您使用相同的端口创建新的TCP客户端时,我猜它正在使用与以前相同的网络流,这是在尝试读取时锁定的。

在捕获内部,您可以尝试

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

这可能有用。但我建议不要在catch中执行此操作,因为您可能会导致另一个异常。我会说尝试阅读一些例子,因为这段代码确实存在其他答案中提到的其他问题。

答案 1 :(得分:0)

你不应该在while(true)循环中读入。更好地检查myStream.Read是否返回0字节或TCP相关异常发生,在这种情况下连接将被关闭我认为,你需要处理资源并重新连接。

在这里您可以找到安全的阅读方法 - http://www.yoda.arachsys.com/csharp/readbinary.html

答案 2 :(得分:-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());
        }
    }
}