Question

I'm working with a windows form application in C#. I'm using a socket client which is connecting in an asynchronous way to a server. I would like the socket to try reconnecting immediately to the server if the connection is broken for any reason. My receive routine looks like this

        public void StartReceiving()
    {
        StateObject state = new StateObject();
        state.workSocket = this.socketClient;
        socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(OnDataReceived), state);
    }

    private void OnDataReceived(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            // Read data from the remote device.
            int iReadBytes = client.EndReceive(ar);
            if (iReadBytes > 0)
            {
                byte[] bytesReceived = new byte[iReadBytes];
                Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes);
                this.responseList.Enqueue(bytesReceived);
                StartReceiving();
                receiveDone.Set();
            }
            else
            {
                NotifyClientStatusSubscribers(false);
            }
        }
        catch (Exception e)
        {

        }
    }

When NotifyClientStatusSubscribers(false) is called the function StopClient is executed:

public void StopClient()
    {
        this.canRun = false;
        this.socketClient.Shutdown(SocketShutdown.Both);
        socketClient.BeginDisconnect(true, new AsyncCallback(DisconnectCallback), this.socketClient);
    }

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

            // Complete the disconnection.
            client.EndDisconnect(ar);

            this.socketClient.Close();
            this.socketClient = null;
        }
        catch (Exception e)
        {

        }
    }

Now I try reconnecting by calling the following functions:

    public void StartClient()
    {
        this.canRun = true;
        this.MessageProcessingThread = new Thread(this.MessageProcessingThreadStart);
        this.MessageProcessingThread.Start();
        this.socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        this.socketClient.LingerState.Enabled = false;
    }

    public void StartConnecting()
    {
        socketClient.BeginConnect(this.remoteEP, new AsyncCallback(ConnectCallback), this.socketClient);
    }

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

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

            // Signal that the connection has been made.
            connectDone.Set();

            StartReceiving();

            NotifyClientStatusSubscribers(true);
        }
        catch(Exception e)
        {
            StartConnecting();
        }
    }

The socket reconnects when the connection is available, but after a couple of seconds I get the following unhandled exception: "A connection request was made on an already connected socket."

How is this possible?

Was it helpful?

Solution

It's possible if you get an exception in ConnectCallback and you've actually connected successfully. Set a break point in the catch statement of the ConnectCallback and see if there is an exception that gets raised there- currently there is nothing that will tell you that you got an exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top