From c730955bd694d6d439efb15ba5577d39dd0522ad Mon Sep 17 00:00:00 2001 From: rackover Date: Mon, 15 Jun 2020 01:14:32 +0200 Subject: [PATCH] Fixed wrong lobby ID returned & stream-locking --- Broadcast/Server.cs | 13 ++++++---- BroadcastClient/Client.cs | 14 ++++++++--- BroadcastShared/Networking.cs | 45 +++++++++++++++++++++++++++++++++-- BroadcastTester/Program.cs | 2 +- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/Broadcast/Server.cs b/Broadcast/Server.cs index 38b41a0..89869ce 100644 --- a/Broadcast/Server.cs +++ b/Broadcast/Server.cs @@ -50,7 +50,9 @@ public Server() try { // BLOCKing var msgBuffer = ns.Read(); - if (msgBuffer.Length == 0) continue; + if (client.Available <= 0 && msgBuffer.Length == 0) { + break; + } var messageType = msgBuffer[0]; byte[] deserializable = new byte[msgBuffer.Length - 1]; @@ -85,7 +87,8 @@ public Server() throw new TaskCanceledException(); } } - client.Dispose(); + ns.Dispose(); + client.Close(); logger.Info("Client ["+clientId+"] is no longer connected (EXIT)"); }).Start(); @@ -188,10 +191,9 @@ void HandleSubmit(byte[] deserializable, TcpClient client, uint clientId) lastHeardAbout[lobby] = DateTime.UtcNow; var id = BitConverter.GetBytes(uIntId); - Array.Reverse(id); client.GetStream().WriteData(id); // I return the ID of the lobby - logger.Info("Finished processing lobby submission from client [{0}]!".Format(clientId)); + logger.Info("Finished processing lobby submission from client [{0}] (gave them ID {1} for their lobby)!".Format(clientId, uIntId)); } void HandleDelete(byte[] deserializable, TcpClient client, uint clientId) @@ -200,7 +202,8 @@ void HandleDelete(byte[] deserializable, TcpClient client, uint clientId) var targetLobby = BitConverter.ToUInt32(deserializable, 0); lock (lobbies) { - lobbies.RemoveAll(o => o.id == targetLobby); + var removed = lobbies.RemoveAll(o => o.id == targetLobby); + logger.Debug("Removed {1} lobbies (every lobby with ID {2}) as requested by client [{0}]".Format(clientId, removed, targetLobby)) ; } logger.Info("Finished removing lobby {1} as requested by client [{0}]".Format(clientId, targetLobby)); } diff --git a/BroadcastClient/Client.cs b/BroadcastClient/Client.cs index 068fbe4..21d0ed3 100644 --- a/BroadcastClient/Client.cs +++ b/BroadcastClient/Client.cs @@ -50,11 +50,17 @@ void Start() { if (client!= null) { logger.Debug("Disposing previous client"); - client.Dispose(); + try { + client.GetStream().Dispose(); + } + catch(InvalidOperationException) { + // Nothing to do + } + client.Close(); } logger.Debug("Instantiating a new client"); client = new TcpClient(address.ToString(), Networking.PORT); - logger.Debug("Done! Setting receivetimeout..."); + logger.Debug("Done! Setting receive timeout..."); client.ReceiveTimeout = SECONDS_BEFORE_EMPTY_READ * 1000; logger.Debug("Set client ReceiveTimeout to " + (SECONDS_BEFORE_EMPTY_READ * 1000)+"ms"); logger.Info("Client connected to "+address+":"+Networking.PORT); @@ -200,10 +206,11 @@ bool ConnectIfNotConnected() } } - public bool IsConnected() + bool IsConnected() { if (client != null && client.Connected) { try { + NetworkStream stream = client.GetStream(); List message = new List(); message.Add(Networking.PROTOCOL_HELLO); @@ -211,6 +218,7 @@ public bool IsConnected() stream.WriteData(message.ToArray()); var data = stream.Read(); + if (data.Length > 0) { return true; } diff --git a/BroadcastShared/Networking.cs b/BroadcastShared/Networking.cs index 2ef557e..5e767da 100644 --- a/BroadcastShared/Networking.cs +++ b/BroadcastShared/Networking.cs @@ -3,6 +3,7 @@ using System.Net.Sockets; using System.Text; using System.Linq; +using System.Threading.Tasks; namespace Broadcast.Shared { @@ -23,6 +24,33 @@ public MessageBuildingException(string msg, byte[] constructed) : base(msg + "\n public const byte VERSION = 5; + static Dictionary isStreamBusy = new Dictionary(); + + static bool IsStreamBusy(this NetworkStream stream) + { + if (!isStreamBusy.ContainsKey(stream)) { + isStreamBusy.Add(stream, false); + } + return isStreamBusy[stream]; + } + + static void Lock(this NetworkStream stream) + { + isStreamBusy[stream] = true; + } + + static void Unlock(this NetworkStream stream) + { + isStreamBusy[stream] = false; + } + + static void WaitForStreamAvailability(this NetworkStream stream) + { + while (IsStreamBusy(stream)) { + Task.WaitAny(Task.Delay(10)); + } + } + public static void WriteData(this NetworkStream stream, byte[] data) { var size = BitConverter.GetBytes(Convert.ToUInt32(data.Length)); @@ -32,16 +60,26 @@ public static void WriteData(this NetworkStream stream, byte[] data) responseList.AddRange(data); var toWrite = responseList.ToArray(); + stream.WaitForStreamAvailability(); + stream.Lock(); + stream.Write(toWrite, 0, toWrite.Length); + + stream.Unlock(); } public static byte[] Read(this NetworkStream stream) { int bites = 0; byte[] sizeBuffer = new byte[4]; // UINT32 is 4 bytes - stream.Read(sizeBuffer, 0, sizeBuffer.Length); + stream.WaitForStreamAvailability(); + stream.Lock(); + + stream.Read(sizeBuffer, 0, sizeBuffer.Length); + var length = BitConverter.ToUInt32(sizeBuffer, 0); + if (length == 0) return new byte[0]; // Garbage // Emptying network buffer from data var remainingData = Convert.ToInt64(length); @@ -56,9 +94,12 @@ public static byte[] Read(this NetworkStream stream) Array.Copy(buffer, shrankArray, shrankArray.Length); data.AddRange(shrankArray); - bites++; + bites++; } + stream.Unlock(); + + // Concatenate data var msgBuffer = data.ToArray(); if (msgBuffer.Length != length) { diff --git a/BroadcastTester/Program.cs b/BroadcastTester/Program.cs index 0439233..30eabcd 100644 --- a/BroadcastTester/Program.cs +++ b/BroadcastTester/Program.cs @@ -12,7 +12,7 @@ static void Main(string[] args) new Task(delegate { new Server.Server(); }).Start(); - new Client.Client("localhost", "test").Test(); + new Client.Client("localhost", "test", true).Test(); } } }