Forum Xamarin.Android

TCP stream recipient failing to recieve data

Hey,

I encountered some strange behaviour when sending byte data over a TCP connection using my local network (no DNS involved).
The recipient does not recieve the data send by my Android device. Recipient does however recieve an empty a byte array.
I made sure that the data has several bytes of data when sending but the recieving device only recieves an empty byte array.

The TCP reader can recieve data properly but sending data does not seem to work for me.
Is there something that blocks Android devices from sending data using TCP?

I made another small .net Core project using the exact same TCP client code that I use in the Android project and it worked as intended, every bit of data is recieved by the tcp connection recipient when sending from my computer.

In my main project the connection is established and the data is sent from an Android service with acquired Internet permission.

This is the code I use to write to the established tcp client stream.

public void WriteToTcp(byte[] message, TcpClient tcpClient)
{       
    if (!tcpClient.Connected) { throw new Exception("Tcp client not connected"); }
    using (var tcpStream = new BinaryWriter(tcpClient.GetStream()))
    {
        tcpStream.Write(message);
        tcpStream.Flush();
    }
}

The reading function is the only other function that uses the same stream, it looks like this:

private static readonly byte[] TcpBuffer = new byte[256];

public async void InitiateTcpLoop(TcpClient tcp)
    {
        if (tcp == null) { throw new ArgumentException("Attempt to read from null tcp connection"); }
        if (!tcp.Connected) { return; }

        var recievedBuffer = new LinkedList<byte>();

        while (tcp.Connected)
        {
            if (tcp.Available == 0)
            {
                await Task.Delay(250);
                continue;
            }

            using (var tcpStream = new BinaryReader(tcp.GetStream()))
            {
                int read;
                while((read = tcpStream.Read(TcpBuffer, 0, TcpBuffer.Length)) > 0)
                {
                    for(var i = 0; i < read; i++){ recievedBuffer.AddLast(TcpBuffer[i]); }
                }

                HandleByteResponse(recievedBuffer.ToArray());
                recievedBuffer.Clear();
            }
        }
}

I would appreciate any insight and technicalities that I may have missed.
Thanks!

Best Answer

  • HannesDevHannesDev ✭✭
    Accepted Answer

    Alright, solved the issue using the following code using callback functions rather than while loops:

    private TcpClient _tcpClient;
    private NetworkStream _tcpStream;
    
    private void SetupTcpListener()
    {
        var buffer = new byte[256];
        _tcpStream.BeginRead(buffer, 0, buffer.Length,
            ar =>
            {
                var read = _tcpStream.EndRead(ar);
                var readBuffer = new byte[read];
                for (var i = 0; i < read; i++) { readBuffer[i] = buffer[i]; }
                HandleByteResponse(readBuffer);
                SetupTcpListener();
            }, null);
    }
    
    public async void WriteToTcp(byte[] data)
    {
        while (!_tcpStream.CanWrite) { await Task.Delay(250); }
        _tcpStream.BeginWrite(data, 0, data.Length, ar =>
        {
            _tcpStream.EndWrite(ar);
            _tcpStream.Flush();
        }, null);
    }
    

    I find this to be better in regards of code quality, maybe a bit harder to grasp at first glance but relatively straight forward.

    Hope this helps!

Answers

  • HannesDevHannesDev Member ✭✭

    I was curious if there was an android issue related to local network communication bypassing hte DNS so I made a project using android studio. My tcp app I made with android studio worked as intended. All sent bytes was also recieved by the recipient device. I figure that there might be a bug with the Xamarin tcp connection using Android devices.

  • HannesDevHannesDev Member ✭✭

    Update: I made a new Xamarin cross platform project and used the exact same code I wrote in my previous comment and sending data seems to work just fine. No clue how any other aspect of the application can stop a newly instantiated TCP stream connection.

  • HannesDevHannesDev Member ✭✭
    Accepted Answer

    Alright, solved the issue using the following code using callback functions rather than while loops:

    private TcpClient _tcpClient;
    private NetworkStream _tcpStream;
    
    private void SetupTcpListener()
    {
        var buffer = new byte[256];
        _tcpStream.BeginRead(buffer, 0, buffer.Length,
            ar =>
            {
                var read = _tcpStream.EndRead(ar);
                var readBuffer = new byte[read];
                for (var i = 0; i < read; i++) { readBuffer[i] = buffer[i]; }
                HandleByteResponse(readBuffer);
                SetupTcpListener();
            }, null);
    }
    
    public async void WriteToTcp(byte[] data)
    {
        while (!_tcpStream.CanWrite) { await Task.Delay(250); }
        _tcpStream.BeginWrite(data, 0, data.Length, ar =>
        {
            _tcpStream.EndWrite(ar);
            _tcpStream.Flush();
        }, null);
    }
    

    I find this to be better in regards of code quality, maybe a bit harder to grasp at first glance but relatively straight forward.

    Hope this helps!

Sign In or Register to comment.