I know that when using TCP (like WebSockets) updating the state of the game every frame is not the most clever way as UDP should be used for this. So I do not plan to do this in practice, but while testing my code I encountered a problem regarding this.
In UDP the problem doesn’t exist.
Here is what I do:
- I use WebSocketNetworkInterface
- I send packet every frame using the pipeline created with CreatePipeline() without any arguments, which in WebSockets will always give me ReliableSequenced as there is no way to change it (as far as I know).
- Server is started and I connect a client to it.
- Then I disconnect the client and most of the times (not always) I get this warning:
My guess is that it is related to the 32 packets in flight limit. Even though the server and the client are on the same machine, they send hundreds of packets per second. So somehow the buffer gets overflowed with the packets that are not confirmed yet. But what is interesting is that it only happens after I disconnect the client.
So I think this warning should not be displayed at all. I do all sort of checks to not use BeginSend and EndSend on connections that are disconnected (code below). And from what I have seen after the disconnection is detected, the BeginSend and EndSend are not being called. Also there is no error at any point returned by BeginSend and EndSend.
What may be important is the fact that I use ScheduleFlushSend().Complete() to send the packets at the end of the frame (to avoid waiting for the next frame and ScheduleUpdate().Complete() that is being called at the beginning of the frame). I also use all BeginSend and EndSend calls just before I flush send. I do all this in LateUpdate() from a script marked as [DefaultExecutionOrder(10000)]. To make sure all the packets will be sent at the very end of the frame.
I think it is potentially something that can be fixed, because I don’t see any point in showing a warning for a connection that was disconnected.
The code I mentioned above, how I check if the packet should be sent:
public static bool CanSendOrReceiveData(NetSocket netSocket, NetworkPipeline networkPipeline, int connectionIndex)
{
if (netSocket.owner == NetSocketOwner.Server && netSocket.status == NetSocketStatus.Connected)
{
if (netSocket.thisAsServer.multiNetworkDriver.IsCreated
&& netSocket.thisAsServer.connections[connectionIndex].isUsed
&& netSocket.thisAsServer.connections[connectionIndex].networkConnection != default
&& netSocket.thisAsServer.multiNetworkDriver.GetConnectionState(netSocket.thisAsServer.connections[connectionIndex].networkConnection) == NetworkConnection.State.Connected
&& (netSocket.thisAsServer.connections[connectionIndex].isConnected
|| (netSocket.thisAsServer.connections[connectionIndex].isWaitingForAuthorization && networkPipeline == netSocket.rpcPipeline)))
return true;
}
else if (netSocket.owner == NetSocketOwner.Client)
{
if (netSocket.thisAsClient.networkDriver.IsCreated
&& netSocket.thisAsClient.clientConnection != default
&& netSocket.thisAsClient.networkDriver.GetConnectionState(netSocket.thisAsClient.clientConnection) == NetworkConnection.State.Connected
&& (netSocket.status == NetSocketStatus.Connected
|| (netSocket.status == NetSocketStatus.ClientWaitingForAuthorization && networkPipeline == netSocket.rpcPipeline)))
return true;
}
return false;
}