properly disconnect local client without freezing by limiting unread message queue length and properly disconnecting when the socket dies

upm
Anton Franzluebbers 2022-03-10 20:08:29 -05:00
parent bca55cccbc
commit 36f16b35df
2 changed files with 60 additions and 19 deletions

View File

@ -211,6 +211,7 @@ namespace VelNet
{ {
} }
private int maxUnreadMessages = 1000;
public readonly List<Message> receivedMessages = new List<Message>(); public readonly List<Message> receivedMessages = new List<Message>();
private void Awake() private void Awake()
@ -233,15 +234,20 @@ namespace VelNet
private void AddMessage(Message m) private void AddMessage(Message m)
{ {
bool added = false;
lock (receivedMessages) lock (receivedMessages)
{ {
//Debug.Log(messagesReceived++); // this is to avoid backups when headset goes to sleep
if (receivedMessages.Count < maxUnreadMessages)
{
receivedMessages.Add(m); receivedMessages.Add(m);
added = true;
}
} }
try try
{ {
MessageReceived?.Invoke(m); if (added) MessageReceived?.Invoke(m);
} }
catch (Exception e) catch (Exception e)
{ {
@ -279,6 +285,7 @@ namespace VelNet
Debug.Log("Received duplicate login message " + userid); Debug.Log("Received duplicate login message " + userid);
return; return;
} }
userid = lm.userId; userid = lm.userId;
Debug.Log("Joined server " + userid); Debug.Log("Joined server " + userid);
@ -529,6 +536,7 @@ namespace VelNet
private void LeaveRoom() private void LeaveRoom()
{ {
Debug.Log("Leaving Room");
string oldRoom = LocalPlayer?.room; string oldRoom = LocalPlayer?.room;
// delete all NetworkObjects that aren't scene objects or are null now // delete all NetworkObjects that aren't scene objects or are null now
objects objects
@ -591,12 +599,37 @@ namespace VelNet
private void DisconnectFromServer() private void DisconnectFromServer()
{ {
LeaveRoom(); Debug.Log("Disconnecting from server");
Debug.Log("Leaving Room");
string oldRoom = LocalPlayer?.room;
// delete all NetworkObjects that aren't scene objects or are null now
objects
.Where(kvp => kvp.Value == null || !kvp.Value.isSceneObject)
.Select(o => o.Key)
.ToList().ForEach(SomebodyDestroyedNetworkObject);
// then remove references to the ones that are left
objects.Clear();
instance.groups.Clear();
foreach (NetworkObject s in sceneObjects)
{
s.owner = null;
}
players.Clear();
masterPlayer = null;
connected = false; connected = false;
udpConnected = false; udpConnected = false;
socketConnection?.Close(); socketConnection?.Close();
clientReceiveThreadUDP?.Abort(); clientReceiveThreadUDP?.Abort();
clientReceiveThread?.Abort(); clientReceiveThread?.Abort();
clientReceiveThread = null;
socketConnection = null; socketConnection = null;
udpSocket = null; udpSocket = null;
} }
@ -637,7 +670,7 @@ namespace VelNet
using BinaryReader reader = new BinaryReader(stream); using BinaryReader reader = new BinaryReader(stream);
//now we are connected, so add a message to the queue //now we are connected, so add a message to the queue
AddMessage(new ConnectedMessage()); AddMessage(new ConnectedMessage());
while (true) while (socketConnection.Connected)
{ {
//read a byte //read a byte
MessageReceivedType type = (MessageReceivedType)stream.ReadByte(); MessageReceivedType type = (MessageReceivedType)stream.ReadByte();
@ -856,15 +889,16 @@ namespace VelNet
/// <summary> /// <summary>
/// Send message to server using socket connection. /// Send message to server using socket connection.
/// <param name="message">We can assume that this message is already formatted, so we just send it</param>
/// </summary> /// </summary>
private static void SendTcpMessage(byte[] message) /// <param name="message">We can assume that this message is already formatted, so we just send it</param>
/// <returns>True if the message successfully sent. False if it failed and we should quit</returns>
private static bool SendTcpMessage(byte[] message)
{ {
// Debug.Log("Sent: " + clientMessage); // Debug.Log("Sent: " + clientMessage);
if (instance.socketConnection == null) if (instance.socketConnection == null)
{ {
Debug.LogError("Tried to send message while socket connection was still null.", instance); Debug.LogError("Tried to send message while socket connection was still null.", instance);
return; return false;
} }
try try
@ -874,7 +908,7 @@ namespace VelNet
{ {
instance.DisconnectFromServer(); instance.DisconnectFromServer();
Debug.LogError("Disconnected from server. Most likely due to timeout."); Debug.LogError("Disconnected from server. Most likely due to timeout.");
return; return false;
} }
// Get a stream object for writing. // Get a stream object for writing.
@ -884,10 +918,18 @@ namespace VelNet
stream.Write(message, 0, message.Length); stream.Write(message, 0, message.Length);
} }
} }
catch (IOException ioException)
{
instance.DisconnectFromServer();
Debug.LogError("Disconnected from server. Most likely due to timeout.\n" + ioException);
return false;
}
catch (SocketException socketException) catch (SocketException socketException)
{ {
Debug.Log("Socket exception: " + socketException); Debug.Log("Socket exception: " + socketException);
} }
return true;
} }
private static byte[] get_be_bytes(int n) private static byte[] get_be_bytes(int n)
@ -1150,7 +1192,6 @@ namespace VelNet
writer.Write((byte)MessageType.Destroy); writer.Write((byte)MessageType.Destroy);
writer.Write(networkId); writer.Write(networkId);
SendToRoom(mem.ToArray(), include_self: false, reliable: true); SendToRoom(mem.ToArray(), include_self: false, reliable: true);
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "edu.uga.engr.vel.velnet", "name": "edu.uga.engr.vel.velnet",
"displayName": "VelNet", "displayName": "VelNet",
"version": "1.0.11", "version": "1.0.12",
"unity": "2019.1", "unity": "2019.1",
"description": "A custom networking library for Unity.", "description": "A custom networking library for Unity.",
"keywords": [ "keywords": [