Search Unity

Client slowly handling packets from custom made server

Discussion in 'Multiplayer' started by Liderluigi, Apr 8, 2017.

  1. Liderluigi

    Liderluigi

    Joined:
    Apr 7, 2017
    Posts:
    2
    Hi!

    Introduction:

    There have been few days since I had this problem and I have not been able to solve it:

    I have a custom Java TCP multithreaded server that interacts with my Unity client. For example client sends "login user pass" packet and Server instantly (and I must mention this now) answers with an "ok" or "fail". There are no problems here.

    My methods:

    Previous "receive" code on Client.cs
    Code (CSharp):
    1.  
    2.  
    3.     private void Update()
    4.     {
    5.         if (socketReady)
    6.         {
    7.             if (socket.GetStream().DataAvailable)  //the problem was this line
    8.             {
    9.                 string recv = encryption(sr.ReadLine());
    10.                 if (recv != null)
    11.                     HandleRecv(recv);
    12.             }
    13.  
    14.         }
    15.     }
    16.  
    17.  
    HandleRecv() method that interacts with Unity Objects
    Code (CSharp):
    1.  
    2.     private bool HandleRecv(string recv)  //handles different packets received from server
    3.     {
    4.         string[] cmd = recv.Split(' ');
    5.         switch (cmd[0])
    6.         {
    7.          
    8.             case "fail":
    9.                 GameManager.Instance.BackButton(); //Here I change scene
    10.                 Debug.Log("Wrong credentials or logged in already!");
    11.                 break;
    12.  
    13.            // etc, i will just post this as example
    14.  
    15.         }
    16.  
    17.         return true;
    18.     }
    The problem:

    The first code I used for Client was a lot simpler and seemed quicker. I could interact with server without any problems. However, once I created the "move" packets (which are a continuous fluctuation of packets almost instantly) I noticed that I could not receive 2 or more packets in a row because of the socket.getStream().DataAvailable line.

    I deleted that line, ok. But then, as the Update() method is the main class thread, when the server didn't send any packets to the client, the game freezed waiting for one.

    So I had to change the code: I removed Update() and created a Recv() thread to act the same way. As this thread was not the main one, the game did not freeze.

    But what happened then? My HandleRecv() method checks the packet that has been received and then INTERACTS WITH UNITY OBJECTS (changes scene, creates game objects, etc.). As this new Recv() thread is not the main thread, I CANNOT INTERACT with those objects.

    What can I do?

    I have thought of multiple solutions, the one I thought for example (but doesnt work well): Using the Update() thread again and creating public variables that are accessed between the 2 threads but this SLOWS A LOT the packet handling! My player movement seems lagged...

    Actual "receive" code on Client.cs (UGLY share of public variable between 2 threads, SLOWS A LOT the game, seems lagged)
    Code (CSharp):
    1.  
    2.     public string recv = null;
    3.     public bool handled = true;
    4.  
    5.  
    6.     public void Recv()  //Thread that reads line from server stream
    7.     {
    8.         if (socketReady)
    9.             while (true)
    10.             {
    11.                 if (handled)
    12.                 {
    13.                     handled = false;
    14.                     recv = encryption(sr.ReadLine());
    15.                 }
    16.             }
    17.     }
    18.  
    19.     private void Update()  //once public variable gets updated, handle it
    20.     {
    21.         if (socketReady)
    22.             if (recv != null)
    23.                 if (HandleRecv(recv))
    24.                 {
    25.                     handled = true;
    26.                     recv = null;
    27.                 }
    28.     }
    I would really appreciate your help!! Thank you in advance!!
     
    Last edited: Apr 8, 2017
  2. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    This is a very common problem in sockets, when dealing with frame loops (such as unity's Update loop). The issue is actually plainly obvious: with your current code, you are only handling one message per frame. In some cases this may be okay but with the fact that lower-end devices and other conditions can result low fps, relying on the processing of a single message per frame will eventually cause problems...

    Your previous Client.cs script was closer to what you want. Simply change the "if" on line 7 to a while loop, and basically handle every message that is available (based on the DataAvailable bool being true) each frame. Some will argue that this is crazy talk, because avoiding frame blockage is of utmost priority, however it should be very unlikely that you reach a point where there are too many messages being sent to cause your while loop to significantly slow down your frames (if this does happen, you are sending far too many messages)...

    Hopefully this helps, good luck!
     
  3. Liderluigi

    Liderluigi

    Joined:
    Apr 7, 2017
    Posts:
    2
    Thanks for the reply and the information you gave me!

    However, I didn't get it to work with the while solution. It acted the same way as my previous code :(

    I hope there's another way to manage sockets on Unity because, on a simple console, communication works perfectly...
     
  4. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    Hmm... in that case I'm not entirely sure what else it could be... sockets can be configured in a multitude of different ways though so it could well be something to do with how you've set up your sockets... for example the default TCP socket can only handle one read/write at a time, and each message has to be acknowledged (because it's a reliable transport protocol)... so you could be suffering from the limitations of TCP or need to further configure the socket. UDP might be a better choice of protocol since you mention networking the movement of objects...

    Have you looked into using unet? Although I am a fan of building your solution from scratch as it gives you more control and more knowledge of what it is that you are doing, I would hate to have to build the sockets part of unet from scratch. I think that part of unet is done really well so if you can, I would definitely recommend investigating the use of unet...
     
  5. Simbird

    Simbird

    Joined:
    Sep 4, 2019
    Posts:
    3

    donnysobonny -- this worked for me, thanks!!!