0

I'm doing an application which require me as a client side to connect to a server and receive data from the server. I will need to do re-connection when the connection is disconnected. Below is my code:

   public enum MySocketState
   {
       Disconnected = 0,
       Connecting,
       Connected
   }

    private Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    private byte[] _recieveBuffer = new byte[128];

    void DataProcess()
    {
        try
        {
            if (_serverSocket == null || sockState == MySocketState.Disconnected)
            {
                Console.WriteLine("Trying to connect...");

                SetupServer();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    private void SetupServer()
    {
        try
        {
            _serverSocket.Connect("192.168.1.11", 1000);
        }
        catch (SocketException ex)
        {
            Console.WriteLine(ex.Message);
        }

        sockState = MySocketState.Connected;
        Console.WriteLine("Server connected...");
        _serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);

    }

    private void ReceiveCallback(IAsyncResult AR)
    {
        try
        {
            if (_serverSocket == null)
                _serverSocket = (Socket)AR.AsyncState;

            int recieved = _serverSocket.EndReceive(AR);

            if (recieved <= 0)
            {
                CloseSocket();
                return;
            }

            byte[] recData = new byte[recieved];
            Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
            string strData = ASCIIEncoding.ASCII.GetString(recData);
            Console.WriteLine(strData);

            //Process the data stored in recData
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            CloseSocket();
        }
        finally
        {
            try
            {
                //Start receiving again
                if (_serverSocket != null)
                    _serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
            }
            catch (Exception ex2)
            { }
        }
    }

    public void CloseSocket()
    {
        try
        {
            if (_serverSocket != null)
            {
                if (_serverSocket.Connected)
                    _serverSocket.Shutdown(SocketShutdown.Both);
                _serverSocket.Close();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        _serverSocket = null;
        sockState = MySocketState.Disconnected;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        DataProcess();
    }

I'm using a timer (timer1_tick) to always detect whether or not the server is connected.

But after it disconnected with the server, it cannot be reconnected back and below is the error message on line _serverSocket.Connect("192.168.1.11", 1000):

A first chance exception of type 'System.NullReferenceException' occurred in fform.exe
System.NullReferenceException: Object reference not set to an instance of an object.
at fform.Form1.SetupServer() in c:\Work\Project 2015\Form1.cs:line 143
at fform.Form1.DataProcess() in c:\Work\Project 2015\Form1.cs:line 79

Do you guys know how come it cannot be connect back?

Coolguy
  • 2,225
  • 12
  • 54
  • 81

1 Answers1

0

Probably it's because you set _serverSocket to null after you CloseSocket() and did not create a new Socket instance when you try to reconnect.

public void CloseSocket()
{
    ...
    _serverSocket = null;
    ...
}

Look at the line number in the error message

at fform.Form1.SetupServer() in c:\Work\Project 2015\Form1.cs:line 143 at fform.Form1.DataProcess() in c:\Work\Project 2015\Form1.cs:line 79

You should probably do the following when you reconnect:

private void SetupServer()
{
    try
    {
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Added
        _serverSocket.Connect("192.168.1.11", 1000);
    }
    ...
}
interceptwind
  • 665
  • 4
  • 14
  • Line 79 refer to line SetupServer() in DataProcess(). Line 143 refers to _serverSocket.Connect("192.168.1.11", 1000) which is what I mentioned in the question. – Coolguy Dec 30 '15 at 02:08
  • exactly what I suspected :) – interceptwind Dec 30 '15 at 02:11
  • refer to http://stackoverflow.com/questions/5910568/reconnect-tcpclient-after-interruption – interceptwind Dec 30 '15 at 02:15
  • I see. Ok Thanks! It works! But then is these coding the best way in terms of connecting and reconnecting to server? I do it another way in http://stackoverflow.com/questions/34521688/using-socket-beginconnect-to-connect-with-server-in-c-sharp-winform-and-the-ia by using BeginConnect() but have problem. Which is the best way? Using direct connect like in this question or BeginConnect()? – Coolguy Dec 30 '15 at 02:25
  • You should use socket.Connect() followed by socket.BeginReceive(). socket.BeginConnect() will connect in another thread, hence socket.BeginReceive() may start receiving messages BEFORE the socket is connected, which is a problem. – interceptwind Dec 30 '15 at 02:33
  • Right way: Connect() in current thread -> Connect Completed -> BeginReceive() – interceptwind Dec 30 '15 at 02:36
  • Wrong way; BeginConnect() asynchronously in another thread -> BeginReceive() -> Error if BeginConnect() not completed – interceptwind Dec 30 '15 at 02:37
  • Ok. Thanks. Then I just use Connect() like what I do in this question. – Coolguy Dec 30 '15 at 02:44