Search code examples
androidunity-game-enginetcpclientsocketexceptionsystem.net.sockets

Is the usage of TcpClients in unity3d for android possible?


I am trying to make an andorid app that commuicates with my server via Unity 5.4. The Devices need to be in the same network to do so.

For that i am using System.Net.Sockets and a TcpClient to connect to my server. Everything works well when i run it out of the Editor, or build it as a Windows standalone.The communication between a pc hosting the service and a diffrent pc running the standalone is possible and working as intended. As soon as i build it as an .apk and install it on my smartphone i will get a SocketException. Also my phone is stuck loading for quite some time

Is using a TcpClient, is that possible on android with unity3d ?

The Exception i get is:

System.Net.Sockets.SocketException: Connection timed out

I made sure that both devices are in the same network, e.g. the Ip for my Pc hosting the server is 192.168.178.24 and the ip for my smartphone is 192.168.178.113.

The ports required are open and the firewall lets data through.

I am runnig this code in Unity:

private TcpClient client;
private StreamWriter writer;

void Start()
{
    try
    {
        client = new TcpClient(AddressFamily.InterNetwork);
        IPAddress ipAddress = IPAddress.Parse(PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey));
        Debug.Log(ipAddress.ToString());
        client.Connect(ipAddress, 11000);
        writer = new StreamWriter(client.GetStream());
        Debug.Log("connected");
    }
    catch (ArgumentNullException ane)
    {
        Debug.Log(string.Format("ArgumentNullException : {0}", ane.ToString()));
    }
    catch (SocketException se)
    {
        Debug.Log(string.Format("SocketException : {0}", se.ToString()));
    }
    catch (Exception e)
    {
        Debug.Log(string.Format("Unexpected exception : {0}", e.ToString()));
    }
}

i double checked if the Ip adress recieved from the player prefs is correct, it is.

Has someone an idea what causes it to not even establish a connection ? I tried Wireshark on my pc, it didn't show any incoming packages, so my guess is the mistake is sometimes during establishing the connection.

Here is an image for my Log output from the smartphone: LogCat Output

Edit: Server Code

public class ServiceListener
{
    public TcpListener Listener;

    public void StartListening()
    {
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = Array.Find<IPAddress>(ipHostInfo.AddressList, ipMatch => ipMatch.AddressFamily == AddressFamily.InterNetwork);
        Listener = new TcpListener(ipAddress, 11000);
        Listener.Start();
    }

    public void StopListening()
    {
        Listener.Stop();
    }
}

static void Main()
    {
        ServiceListener currentListener = new ServiceListener();
        currentListener.StartListening();

        TcpClient currentClient = currentListener.Listener.AcceptTcpClient();
        StreamReader reader = new StreamReader(currentClient.GetStream());

        Console.WriteLine("Connected");

        while (true)
        {
            byte[] messageBytes = new byte[1024];


            if (!reader.EndOfStream)
            {

                string message = reader.ReadLine();
                string[] messageParts = message.Split('|');

                int xOffset = int.Parse(messageParts[0]);
                int yOffset = int.Parse(messageParts[1]);
                bool leftClick = bool.Parse(messageParts[2]);
                bool rightClick = bool.Parse(messageParts[3]);


                Console.WriteLine(string.Format("x:{0},y:{1},left:{2},right:{3}", xOffset, yOffset, leftClick, rightClick));
            }
            else
            {
                currentClient = currentListener.Listener.AcceptTcpClient();
                reader = new StreamReader(currentClient.GetStream());
            }
        }
    }

Solution

  • Is using a TcpClient, is that possible on android with unity3d ?

    Yes, it is. It is very possible and should work.

    Your problem is very likely to come from this line of code:

    IPAddress ipAddress = IPAddress.Parse(PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey));
    

    Since your hosting server IP is 192.168.178.24. Hardcode the value for testing purposes to see if PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey) is returning an invalid IP Address.

    Maybe something like:

    IPAddress ipAddress = IPAddress.Parse("192.168.178.24");
    

    Another thing to do in your server code is to put Application.runInBackground = true; in your Start() function. This will make sure that your server is running even when the Applciation is not on focus.

    Finally, you are currently using synchronous server socket. When connecting, receiving data from the server, Unity will block/freeze until that operation completes. You should use asynchronous socket or run your server and client code in another Thread. This does not look like the current problem but you will run into it later on.