Problem with reconnecting in the unity transport

hello
Im using this code for reconnect the client to the server

    if (_serverEndPoint.IsValid && !_networkConnection.IsCreated)
        {
             _networkConnection = _clientDrive.Connect(_serverEndPoint);//handle background stuff
            print("Re-connecting...");
        }

the mentioned code works fine for the first time that the client wants to connect to the server . when I interrupt the internet for 30 s unity transport server disconnect the client when I try to reconnect the client to the server with this code :

            if (!_serverEndPoint.IsValid)
                {
                    _networkConnection = _clientDrive.Connect(_serverEndPoint);
 
                    print("Re-connecting...");
                }

I face with this error and never connect again :

Cannot send data while connecting
0x00007ff73825596c (Unity) StackWalker::GetCurrentCallstack
0x00007ff73825dd49 (Unity) StackWalker::ShowCallstack
0x00007ff73976525c (Unity) GetStacktrace
0x00007ff73a88be43 (Unity) DebugStringToFile
0x00007ff7382be246 (Unity) DebugLogHandler_CUSTOM_Internal_Log
0x0000019e294b313b (Mono JIT Code) (wrapper managed-to-native) UnityEngine.DebugLogHandler:Internal_Log (UnityEngine.LogType,UnityEngine.LogOption,string,UnityEngine.Object)
0x0000019e294b2fdb (Mono JIT Code) UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
0x0000019e294b24fe (Mono JIT Code) UnityEngine.Logger:Log (UnityEngine.LogType,object)
0x0000019e298a72aa (Mono JIT Code) UnityEngine.Debug:LogError (object)
0x0000019e29851633 (Mono JIT Code) [NetworkDriver.cs:162] Unity.Networking.Transport.NetworkDriver/Concurrent:BeginSend (Unity.Networking.Transport.NetworkPipeline,Unity.Networking.Transport.NetworkConnection,Unity.Networking.Transport.DataStreamWriter&,int)
0x0000019e2984ff13 (Mono JIT Code) [NetworkDriver.cs:970] Unity.Networking.Transport.NetworkDriver:BeginSend (Unity.Networking.Transport.NetworkPipeline,Unity.Networking.Transport.NetworkConnection,Unity.Networking.Transport.DataStreamWriter&,int)
0x0000019e2984ed7b (Mono JIT Code) [ClientCode.cs:263] ClientCode:SendUnReliableDataToServer (byte[])
0x0000019e2984e84b (Mono JIT Code) [SendAllDataToServer.cs:133] SendAllDataToServer:SendUnreliablePositionToServer (int,single,single,single,single,single,single)
0x0000019e2983172b (Mono JIT Code) [SendAllDataToServer.cs:26] SendAllDataToServer:Update ()
0x0000019e2cebd968 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007ffd1be9e650 (mono-2.0-bdwgc) [mini-runtime.c:2812] mono_jit_runtime_invoke
0x00007ffd1be22ae2 (mono-2.0-bdwgc) [object.c:2921] do_runtime_invoke
0x00007ffd1be2bb3f (mono-2.0-bdwgc) [object.c:2968] mono_runtime_invoke
0x00007ff7380dd844 (Unity) scripting_method_invoke
0x00007ff7380d6195 (Unity) ScriptingInvocation::Invoke
0x00007ff738083614 (Unity) MonoBehaviour::CallMethodIfAvailable
0x00007ff73808371c (Unity) MonoBehaviour::CallUpdateMethod
0x00007ff73754ada8 (Unity) BaseBehaviourManager::CommonUpdate<BehaviourManager>
0x00007ff737554cfa (Unity) BehaviourManager::Update
0x00007ff7379bd66a (Unity) `InitPlayerLoopCallbacks'::`2'::UpdateScriptRunBehaviourUpdateRegistrator::Forward
0x00007ff73799e1bc (Unity) ExecutePlayerLoop
0x00007ff73799e293 (Unity) ExecutePlayerLoop
0x00007ff7379a50c9 (Unity) PlayerLoop
0x00007ff738dee2b1 (Unity) PlayerLoopController::UpdateScene
0x00007ff738debf46 (Unity) Application::TickTimer
0x00007ff73976ea51 (Unity) MainMessageLoop
0x00007ff739772a91 (Unity) WinMain
0x00007ff73b5ba396 (Unity) __scrt_common_main_seh
0x00007ffd6f1b7034 (KERNEL32) BaseThreadInitThunk
0x00007ffd71102651 (ntdll) RtlUserThreadStart

If you want to check if a connection is alive, you should use the NetworkDriver.GetConnectionState method. Checking IsValid on a network endpoint will only tell you if that endpoint is well-formatted (basically if the IP address is valid).

1 Like

hi @simon-lemay-unity
I used what you recommended, this is my code

        if (_clientDrive.GetConnectionState(_networkconnection) == NetworkConnection.State.Disconnected)
        {
           print("client is disconnected.....");
            _clientDisConnectedOnce = true;
        }
        if (_clientDrive.GetConnectionState(_networkconnection) == NetworkConnection.State.Connecting && _clientDisConnectedOnce)
        {
            print("client is connecting.....");
            _networkconnection = _clientDrive.Connect(_serverEndPoint);
        }

I let the client connect first then I closed the server and I wait until the client disconnect completely, the first problem is it takes about 30 s until _clientDrive.GetConnectionState(_networkconnection) find out client has disconnected. and 30s is too much for an online multiplayer game. is there any faster way to find out the server is faced with a problem and let the client know?
the second problem is when the client disconnected, it wouldn’t reconnect with this code could you guide me on how to solve it?

If your server exits gracefully, it can call Disconnect on all its active connections and the clients will be notified without delay (well, with the delay it takes for the message to make it to them).

If your server doesn’t exit gracefully (say it crashes), then the 30 seconds timeout can be reduced. With the new settings API (version 1.0.0-pre.8 or above), you can configure it in the driver like so:

var settings = new NetworkSettings();
settings.WithNetworkConfigParameters(disconnectTimeoutMS: 2000);
var driver = NetworkDriver.Create(settings);

This would set the timeout to 2 seconds.

Is there any reason you’re checking for the Connecting state in the second conditional statement? That state only occurs after calling Connect and before the connection handshake completes. Once the handshake is completed, the state becomes Connected. And once the connection fails, it becomes Disconnected.

1 Like

thank you man , that’s worked perfectly.
when server crashes the client connection will completely lost,for Reconnecting I used _networkconnection = _clientDrive.Connect(_serverEndPoint); but it didn’t work , I initialized the connection and it worked correctly.

   var settings = new NetworkSettings();
        settings.WithNetworkConfigParameters(disconnectTimeoutMS: 2000);
        _clientDrive = NetworkDriver.Create(settings);
        _reliablePipline = _clientDrive.CreatePipeline(typeof(ReliableSequencedPipelineStage));
        _unreliablePipline = _clientDrive.CreatePipeline(typeof(UnreliableSequencedPipelineStage));
        if (_clientInfo._connectToVsp)
        {
            IPHostEntry iPHostEntry = Dns.GetHostEntry(_clientInfo._vpsDomain);

            _serverEndPoint = NetworkEndPoint.Parse(iPHostEntry.AddressList[0].ToString(), _clientInfo._port);
 
        }
        else
        {

            _serverEndPoint = NetworkEndPoint.Parse(_clientInfo._localIp, _clientInfo._port);
        }
        _networkconnection = _clientDrive.Connect(_serverEndPoint);
  1. do you know a better method for reconnecting client connection when the server is live after crashing?
  2. Is there a way for the server to find out the client connection has disconnected less than 30s?

Unfortunately, no. Periodically attempting to reconnect to the server is typically how it’s done.

Same way as on the client. The disconnect timeout setting can also be applied to the server. Just need to apply the setting when creating the server’s driver.