Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Dec 8, 2022, between 7 am & 7 pm EST, in the DOTS Dev Blitz Day 2022 - Q&A forum, Discord, and Unity3D Subreddit to learn more about DOTS directly from the Unity Developers.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Lag on server showing disconnect from client

Discussion in 'Unity Transport' started by pat_trick, Jul 24, 2022.

  1. pat_trick

    pat_trick

    Joined:
    May 23, 2016
    Posts:
    27
    I'm currently using Transport 1.0.0 for both my client and server logic.

    When I connect with a client, I show a log message on my server showing there is an incoming connection. The server also logs a message when I have a disconnection from a client.

    However, when I close the connection from my client using the
    NetworkConnection.Disconnect(NetworkDriver)
    method, my client shows an immediate disconnect, but the server lags for at least 30 seconds before registering the disconnection and displaying its log message.

    I'm wondering if this is on purpose, some lag on the server side due to my code, or some other method?

    Here is the code for the server where it parses incoming commands. There is logic there to handle a Disconnect event but it doesn't seem to occur immediately when I send the disconnect; like I said, it seems to wait for a timeout before registering that the client has actually disconnected.

    Code (CSharp):
    1. protected virtual void UpdateMessagePump()
    2.     {
    3.         // Object for handling incoming data from one or more clients.
    4.         DataStreamReader dataStreamReader;
    5.         // Iterate through all active network connections.
    6.         for (int i = 0; i < netConnections.Length; i++)
    7.         {
    8.             NetworkEvent.Type netEventType;
    9.             while ((netEventType = netDriver.PopEventForConnection(netConnections[i], out dataStreamReader)) != NetworkEvent.Type.Empty)
    10.             {
    11.                 // Handle the event if it is data coming in
    12.                 if (netEventType == NetworkEvent.Type.Data)
    13.                 {
    14.                     // Parse the incoming data for OpCode and act accordingly.
    15.                     ParseDataMessage(dataStreamReader);
    16.                 }
    17.                 // Handle any disconnections and clean up.
    18.                 else if (netEventType == NetworkEvent.Type.Disconnect)
    19.                 {
    20.                     Debug.Log("Client disconnected from server");
    21.                     netConnections[i] = default(NetworkConnection);
    22.                 }
    23.             }
    24.         }
    25.     }
     
  2. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    150
    What you're observing is likely the connection being closed due to timing out because of inactivity, meaning the disconnect message doesn't make it to the server.

    The likeliest cause for this issue is not ensuring that the disconnect message gets sent. It's a bit counter-intuitive, but calling
    NetworkConnection.Disconnect
    doesn't immediately cause the disconnect message to be sent. It only queues it up to be sent later (we don't send it immediately because network I/O is expensive and we rather do that in a job for performance). You would need to schedule an update of the driver (
    NetworkDriver.ScheduleUpdate
    ) or a flush of the send queue (
    NetworkDriver.ScheduleFlushSend
    ) and complete the resulting job to ensure the disconnect message is sent. Here's an example:
    Code (CSharp):
    1. connection.Disconnect(driver);
    2. driver.ScheduleFlushSend(default).Complete();
    Note that if the disconnect message gets lost on the way, there's no attempt to resend it and you'll hit the same timeout of 30 seconds before seeing the disconnect event. You can modify the value of this timeout when creating the driver:
    Code (CSharp):
    1. var settings = new NetworkSettings();
    2. settings.WithNetworkConfigParameters(disconnectTimeoutMS: 10000);
    3. var driver = NetworkDriver.Create(settings);
    The above code will set the timeout to 10 seconds. If you're going to set the timeout very low (say 2 or 3 seconds), I'd recommend also configuring heartbeats (parameter
    heartbeatTimeoutMS
    ) to ensure that connections are not closed if they're just quiet for a bit.
     
    pat_trick likes this.
  3. pat_trick

    pat_trick

    Joined:
    May 23, 2016
    Posts:
    27
    Wonderful, thank you for the explanation! I did have a
    ScheduleUpdate()
    elsewhere in my client code for regular messaging, so it makes sense that this would need to occur for the last disconnect message as well.

    I am fine with a 30 second timeout on the server otherwise as a failsafe in case the client's disconnect message doesn't make it, but good to know I can adjust that as well.