Search code examples
c#xamarin.androidtcpclientnetworkstreamdisconnection

Network stream no longer works after connection loss


I'm working on an android app in xamarin which connects to a server. The server application follows processes etc based on the client connection. However if I say turn the device into airplane mode then turn airplane mode back off the connection no longer works. Basically in the real world the problem is that users will be using the android device which is liable to brief losses of connection due to wifi disturbances etc. I have tried a "reconnect" technique(as i noticed the Tcp.Connected value was still true) by simply trying to reaqcuire the NetworkStream however it did not work. Below is code:

    public NetworkStream NetworkStream;
    public TcpClient TcpClient;
    public string LastGetData = null;
    public string LastPostData = null;
    public bool Disconnected = true;

    public Stream InitializeStream(IPAddressAndPort ipObject)
    {
        NetworkStream clientStream = null;

        try
        {
            IPAddress address = IPAddress.Parse(ipObject.Address);

            TcpClient client = new TcpClient();

            client.SendTimeout = 3000;

            IPEndPoint serverEndPoint = new IPEndPoint(address, ipObject.Port);

            client.ConnectAsync(serverEndPoint.Address, serverEndPoint.Port).Wait(5000);

            if (client.Connected)
            {
                clientStream = client.GetStream();

                TcpClient = client;
                NetworkStream = clientStream;
                Disconnected = false;

                SendData("CLIENTSOFTWARENAME");
                string initReturnValue = ReadData();

                LastGetData = initReturnValue;
            }
        }
        catch (Exception ex)
        {
            LastGetData = ex.Message;
        }

        return clientStream;
    }

    public void AttemptReconnect()
    {
        if (TcpClient != null)
        {
            try
            {
                if (TcpClient.Connected)
                {
                    NetworkStream clientStream = TcpClient.GetStream();

                    NetworkStream = clientStream;
                    Disconnected = false;
                }
            }
            catch (Exception ex)
            {
                LastGetData = ex.Message;
            }
        }
    }

    public string RunCommand(string dataToSend)
    {
        string returnValue = string.Empty;
        try
        {
            if (Disconnected) AttemptReconnect();

            SendData(dataToSend);
            returnValue = ReadData();

            if (returnValue == string.Empty)
                Disconnected = true;
        }
        catch
        {
            returnValue = "An error occured during the action!  Please logout and try again.";
        }
        return returnValue;
    }

    public void SendData(string dataToSend)
    {
        if (NetworkStream != null)
        {
            var serverStream = NetworkStream;

            byte[] outStream = System.Text.Encoding.UTF8.GetBytes(dataToSend);
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            LastPostData = dataToSend;
        }
    }

    public string ReadData()
    {
        if (NetworkStream != null)
        {
            string returnValue = string.Empty;
            byte[] bReads = new byte[1024];
            int readAmount = 0;
            DateTime endProcess = DateTime.Now.AddSeconds(20);

            while (returnValue == string.Empty && endProcess > DateTime.Now)
            {
                while (NetworkStream.DataAvailable)
                {
                    readAmount = NetworkStream.Read(bReads, 0, bReads.Length);
                    returnValue += string.Format("{0}", Encoding.UTF8.GetString(bReads, 0, readAmount));
                }
            }

            LastGetData = returnValue;

            return returnValue;
        }

        return null;
    }

Solution

  • Solved: Once NetworkStream or TCPClient erros out it becomes useless. We decided to store information about the device in order to reconnect to existing process and create a new TCPClient and NetworkStream