Search code examples
c#mvvmxamarin.formstcpclienttcpserver

How to do proper TCP client-side communication with server in xamarin forms?


I`m trying to see what is wrong with my code for a tcp connection to a server in xamarin forms using the mvvm architecture. The client is connecting but when using streamReader.readLine() i get the following error:

System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block.

I´m using xamarin forms and System.Net.Sockets for the TcpClient instance. I´m trying synchronous communication for testing with the server.

I Have a TcpServer program proven to work with other devices. Below is some code to do the communication

The ViewModel of the connection properties page has the following code:

     public ICommand TestConnectionCommand { get { return new 
    RelayCommand(sendMsg); } }
    public ICommand ConnectCommand { get; set; }

    public void sendMsg()
    {
        this.Response = new Response();
        this.EthernetConn.Port = 9091;
        this.EthernetConn.Ip = SelectedDevice.Ip;

        if (String.IsNullOrEmpty(EthernetConn.Ip))
        {
            Application.Current.MainPage.DisplayAlert(Languages.Error, Languages.IpValidation, Languages.Accept);
            return;
        }

        if (String.IsNullOrEmpty(EthernetConn.Timeout))
        {
            Application.Current.MainPage.DisplayAlert(Languages.Error, Languages.TimeoutValidation, Languages.Accept);
            return;
        }

        this.EthernetConn.Message = "TESTING\n";
        tcpService.Initialize(this.ethernetConn);
        this.Response.Message = tcpService.sendMessage(this.EthernetConn);

        if (this.Response.Message.Contains("FormatException"))
        {
            this.Response.IsSuccess = false;
            Application.Current.MainPage.DisplayAlert(Languages.Error, Languages.FormatValidation, Languages.Accept);
            this.IsRunning = false;
            this.IsEnabled = true;
            return;

        }
        else if (this.Response.Message.Contains("ArgumentNullException"))
        {
            this.Response.IsSuccess = false;
            Application.Current.MainPage.DisplayAlert(Languages.Error, this.Response.Message, Languages.Accept);
            this.IsRunning = false;
            this.IsEnabled = true;
            return;

        }
        else if (this.Response.Message.Contains("SocketException"))
        {
            this.Response.IsSuccess = false;
             Application.Current.MainPage.DisplayAlert(Languages.Error, this.Response.Message, Languages.Accept);
            this.IsRunning = false;
            this.IsEnabled = true;
            return;

        }
        else if (this.Response.Message.Contains("OK"))
        {
            this.Response.IsSuccess = true;
        }

        if (this.Response.IsSuccess)
        {
             Application.Current.MainPage.DisplayAlert(Languages.Success, Languages.ConnEstablished, Languages.Accept);
            this.IsRunning = false;
            this.IsEnabled = true;
        }
        else
        {
            Application.Current.MainPage.DisplayAlert(Languages.Error, Languages.ConnFailed, Languages.Accept);
            this.IsRunning = false;
            this.IsEnabled = true;
        }

    }

tcpService is an instance of TCPService, which has the Initialize function to establish connection and the sendMessage function where the error appears to be:

    public void Initialize(EthernetConnection eth)
    {
        client.SendTimeout = Convert.ToInt16(eth.Timeout);
        client.ReceiveTimeout = Convert.ToInt16(eth.Timeout);
        client.Connect(eth.Ip, eth.Port);
    }


    public string sendMessage(EthernetConnection eth)
    {
        string response = String.Empty;
        try
        {
            if (!client.Connected)
            {
                return null;
            }
            var writer = new StreamWriter(client.GetStream());
            writer.WriteLine(eth.Message);

           //Here is where the problem seems to be:
            var reader = new StreamReader(client.GetStream());
            response = reader.ReadLine();

            return response;
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine("ArgumentNullException: {0}", e);
            return "ArgumentNullException: " + e;
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
            return "SocketException:: " + e;
        }
        catch (FormatException e)
        {
            Console.WriteLine("SocketException: {0}", e);
            return "FormatException: " + e;
        }

        }

I would be expecting to read the data in the ReadLine function. Also, I had some printing on the console on the server side if it recieves data and i'm seeing it is not.

Could somebody help me on where could I be wrong? A proven solution is also fine!

Thank you so much!


Solution

  • Whenever you use StreamWriter you need to Flush() the contents of the stream. I'll quote MSDN as the reason becomes quite clear:

    Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.

    You can use it like this:

     var writer = new StreamWriter(client.GetStream());
     writer.AutoFlush = true;
     writer.WriteLine(eth.Message);
     writer.Flush();
    

    And there is a simple demo you can check: https://thuru.net/2012/01/07/simple-clientserver-in-c/