mirror of https://github.com/quasar/Quasar.git
Better handling of many simultaneous connections/disconnections
This commit is contained in:
parent
626646aa46
commit
bda1c5ed1d
|
@ -99,7 +99,6 @@ namespace xClient.Core.Utilities
|
||||||
private void Unsubscribe()
|
private void Unsubscribe()
|
||||||
{
|
{
|
||||||
if (_mEvents == null) return;
|
if (_mEvents == null) return;
|
||||||
|
|
||||||
_mEvents.KeyDown -= OnKeyDown;
|
_mEvents.KeyDown -= OnKeyDown;
|
||||||
_mEvents.KeyUp -= OnKeyUp;
|
_mEvents.KeyUp -= OnKeyUp;
|
||||||
_mEvents.KeyPress -= OnKeyPress;
|
_mEvents.KeyPress -= OnKeyPress;
|
||||||
|
|
|
@ -74,6 +74,7 @@ namespace xClient
|
||||||
if (_msgLoop != null)
|
if (_msgLoop != null)
|
||||||
{
|
{
|
||||||
_msgLoop.ExitThread();
|
_msgLoop.ExitThread();
|
||||||
|
_msgLoop.Dispose();
|
||||||
_msgLoop = null;
|
_msgLoop = null;
|
||||||
}
|
}
|
||||||
MutexHelper.CloseMutex();
|
MutexHelper.CloseMutex();
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace xServer.Core.Networking
|
||||||
/// <param name="client">The connected client.</param>
|
/// <param name="client">The connected client.</param>
|
||||||
private void OnClientConnected(Client client)
|
private void OnClientConnected(Client client)
|
||||||
{
|
{
|
||||||
|
if (ProcessingDisconnect || !Listening) return;
|
||||||
var handler = ClientConnected;
|
var handler = ClientConnected;
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +58,7 @@ namespace xServer.Core.Networking
|
||||||
/// <param name="client">The disconnected client.</param>
|
/// <param name="client">The disconnected client.</param>
|
||||||
private void OnClientDisconnected(Client client)
|
private void OnClientDisconnected(Client client)
|
||||||
{
|
{
|
||||||
|
if (ProcessingDisconnect || !Listening) return;
|
||||||
var handler = ClientDisconnected;
|
var handler = ClientDisconnected;
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -224,7 +224,7 @@ namespace xServer.Core.Networking
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the server is currently processing Disconnect method.
|
/// Determines if the server is currently processing Disconnect method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _processing;
|
protected bool ProcessingDisconnect { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor of the server, initializes variables.
|
/// Constructor of the server, initializes variables.
|
||||||
|
@ -256,7 +256,7 @@ namespace xServer.Core.Networking
|
||||||
_handle.Bind(new IPEndPoint(IPAddress.Any, port));
|
_handle.Bind(new IPEndPoint(IPAddress.Any, port));
|
||||||
_handle.Listen(1000);
|
_handle.Listen(1000);
|
||||||
|
|
||||||
_processing = false;
|
ProcessingDisconnect = false;
|
||||||
|
|
||||||
OnServerState(true);
|
OnServerState(true);
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ namespace xServer.Core.Networking
|
||||||
/// <param name="client">The client to remove.</param>
|
/// <param name="client">The client to remove.</param>
|
||||||
private void RemoveClient(Client client)
|
private void RemoveClient(Client client)
|
||||||
{
|
{
|
||||||
if (_processing) return;
|
if (ProcessingDisconnect) return;
|
||||||
|
|
||||||
lock (_clientsLock)
|
lock (_clientsLock)
|
||||||
{
|
{
|
||||||
|
@ -373,8 +373,8 @@ namespace xServer.Core.Networking
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
if (_processing) return;
|
if (ProcessingDisconnect) return;
|
||||||
_processing = true;
|
ProcessingDisconnect = true;
|
||||||
|
|
||||||
if (_handle != null)
|
if (_handle != null)
|
||||||
{
|
{
|
||||||
|
@ -406,7 +406,7 @@ namespace xServer.Core.Networking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_processing = false;
|
ProcessingDisconnect = false;
|
||||||
OnServerState(false);
|
OnServerState(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace xServer.Core.Packets
|
||||||
{
|
{
|
||||||
public static void HandlePacket(Client client, IPacket packet)
|
public static void HandlePacket(Client client, IPacket packet)
|
||||||
{
|
{
|
||||||
if (client == null || !client.Authenticated || client.Value == null)
|
if (client == null || client.Value == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var type = packet.GetType();
|
var type = packet.GetType();
|
||||||
|
|
|
@ -24,8 +24,11 @@ namespace xServer.Forms
|
||||||
private const int STATUS_ID = 4;
|
private const int STATUS_ID = 4;
|
||||||
private const int USERSTATUS_ID = 5;
|
private const int USERSTATUS_ID = 5;
|
||||||
|
|
||||||
private readonly object _lockClients = new object();
|
|
||||||
private bool _titleUpdateRunning;
|
private bool _titleUpdateRunning;
|
||||||
|
private bool _processingClientConnections;
|
||||||
|
private readonly Queue<KeyValuePair<Client, bool>> _clientConnections = new Queue<KeyValuePair<Client, bool>>();
|
||||||
|
private readonly object _processingClientConnectionsLock = new object();
|
||||||
|
private readonly object _lockClients = new object(); // lock for clients-listview
|
||||||
|
|
||||||
private void ShowTermsOfService()
|
private void ShowTermsOfService()
|
||||||
{
|
{
|
||||||
|
@ -129,6 +132,8 @@ namespace xServer.Forms
|
||||||
{
|
{
|
||||||
this.Invoke((MethodInvoker) delegate
|
this.Invoke((MethodInvoker) delegate
|
||||||
{
|
{
|
||||||
|
if (!listening)
|
||||||
|
lstClients.Items.Clear();
|
||||||
listenToolStripStatusLabel.Text = listening ? string.Format("Listening on port {0}.", port) : "Not listening.";
|
listenToolStripStatusLabel.Text = listening ? string.Format("Listening on port {0}.", port) : "Not listening.";
|
||||||
});
|
});
|
||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
|
@ -140,28 +145,95 @@ namespace xServer.Forms
|
||||||
|
|
||||||
private void ClientConnected(Client client)
|
private void ClientConnected(Client client)
|
||||||
{
|
{
|
||||||
AddClientToListview(client);
|
lock (_clientConnections)
|
||||||
if (Settings.ShowPopup)
|
{
|
||||||
ShowPopup(client);
|
if (!ListenServer.Listening) return;
|
||||||
|
_clientConnections.Enqueue(new KeyValuePair<Client, bool>(client, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_processingClientConnectionsLock)
|
||||||
|
{
|
||||||
|
if (!_processingClientConnections)
|
||||||
|
{
|
||||||
|
_processingClientConnections = true;
|
||||||
|
ThreadPool.QueueUserWorkItem(ProcessClientConnections);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClientDisconnected(Client client)
|
private void ClientDisconnected(Client client)
|
||||||
{
|
{
|
||||||
RemoveClientFromListview(client);
|
lock (_clientConnections)
|
||||||
|
{
|
||||||
|
if (!ListenServer.Listening) return;
|
||||||
|
_clientConnections.Enqueue(new KeyValuePair<Client, bool>(client, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_processingClientConnectionsLock)
|
||||||
|
{
|
||||||
|
if (!_processingClientConnections)
|
||||||
|
{
|
||||||
|
_processingClientConnections = true;
|
||||||
|
ThreadPool.QueueUserWorkItem(ProcessClientConnections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessClientConnections(object state)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
KeyValuePair<Client, bool> client;
|
||||||
|
lock (_clientConnections)
|
||||||
|
{
|
||||||
|
if (!ListenServer.Listening)
|
||||||
|
{
|
||||||
|
_clientConnections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_clientConnections.Count == 0)
|
||||||
|
{
|
||||||
|
lock (_processingClientConnectionsLock)
|
||||||
|
{
|
||||||
|
_processingClientConnections = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = _clientConnections.Dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.Key != null)
|
||||||
|
{
|
||||||
|
switch (client.Value)
|
||||||
|
{
|
||||||
|
case true:
|
||||||
|
AddClientToListview(client.Key);
|
||||||
|
if (Settings.ShowPopup)
|
||||||
|
ShowPopup(client.Key);
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
RemoveClientFromListview(client.Key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the tooltip text of the listview item of a client.
|
/// Sets the tooltip text of the listview item of a client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The client on which the change is performed.</param>
|
/// <param name="client">The client on which the change is performed.</param>
|
||||||
/// <param name="text">The new tooltip text.</param>
|
/// <param name="text">The new tooltip text.</param>
|
||||||
public void SetToolTipText(Client c, string text)
|
public void SetToolTipText(Client client, string text)
|
||||||
{
|
{
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lstClients.Invoke((MethodInvoker) delegate
|
lstClients.Invoke((MethodInvoker) delegate
|
||||||
{
|
{
|
||||||
var item = GetListViewItemByClient(c);
|
var item = GetListViewItemByClient(client);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
item.ToolTipText = text;
|
item.ToolTipText = text;
|
||||||
});
|
});
|
||||||
|
@ -177,7 +249,7 @@ namespace xServer.Forms
|
||||||
/// <param name="client">The client to add.</param>
|
/// <param name="client">The client to add.</param>
|
||||||
private void AddClientToListview(Client client)
|
private void AddClientToListview(Client client)
|
||||||
{
|
{
|
||||||
if (client == null || !client.Authenticated) return;
|
if (client == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -207,9 +279,11 @@ namespace xServer.Forms
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a connected client from the Listview.
|
/// Removes a connected client from the Listview.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The client to remove.</param>
|
/// <param name="client">The client to remove.</param>
|
||||||
private void RemoveClientFromListview(Client c)
|
private void RemoveClientFromListview(Client client)
|
||||||
{
|
{
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lstClients.Invoke((MethodInvoker) delegate
|
lstClients.Invoke((MethodInvoker) delegate
|
||||||
|
@ -217,7 +291,7 @@ namespace xServer.Forms
|
||||||
lock (_lockClients)
|
lock (_lockClients)
|
||||||
{
|
{
|
||||||
foreach (ListViewItem lvi in lstClients.Items.Cast<ListViewItem>()
|
foreach (ListViewItem lvi in lstClients.Items.Cast<ListViewItem>()
|
||||||
.Where(lvi => lvi != null && c.Equals(lvi.Tag)))
|
.Where(lvi => lvi != null && client.Equals(lvi.Tag)))
|
||||||
{
|
{
|
||||||
lvi.Remove();
|
lvi.Remove();
|
||||||
break;
|
break;
|
||||||
|
@ -234,15 +308,17 @@ namespace xServer.Forms
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the status of a client.
|
/// Sets the status of a client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The client to update the status of.</param>
|
/// <param name="client">The client to update the status of.</param>
|
||||||
/// <param name="text">The new status.</param>
|
/// <param name="text">The new status.</param>
|
||||||
public void SetStatusByClient(Client c, string text)
|
public void SetStatusByClient(Client client, string text)
|
||||||
{
|
{
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lstClients.Invoke((MethodInvoker) delegate
|
lstClients.Invoke((MethodInvoker) delegate
|
||||||
{
|
{
|
||||||
var item = GetListViewItemByClient(c);
|
var item = GetListViewItemByClient(client);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
item.SubItems[STATUS_ID].Text = text;
|
item.SubItems[STATUS_ID].Text = text;
|
||||||
});
|
});
|
||||||
|
@ -255,18 +331,17 @@ namespace xServer.Forms
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the user status of a client.
|
/// Sets the user status of a client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <param name="client">The client to update the user status of.</param>
|
||||||
/// Can be "Active" or "Idle".
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="c">The client to update the user status of.</param>
|
|
||||||
/// <param name="userStatus">The new user status.</param>
|
/// <param name="userStatus">The new user status.</param>
|
||||||
public void SetUserStatusByClient(Client c, UserStatus userStatus)
|
public void SetUserStatusByClient(Client client, UserStatus userStatus)
|
||||||
{
|
{
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lstClients.Invoke((MethodInvoker) delegate
|
lstClients.Invoke((MethodInvoker) delegate
|
||||||
{
|
{
|
||||||
var item = GetListViewItemByClient(c);
|
var item = GetListViewItemByClient(client);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
item.SubItems[USERSTATUS_ID].Text = userStatus.ToString();
|
item.SubItems[USERSTATUS_ID].Text = userStatus.ToString();
|
||||||
});
|
});
|
||||||
|
@ -279,16 +354,18 @@ namespace xServer.Forms
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the Listview item which belongs to the client.
|
/// Gets the Listview item which belongs to the client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The client to get the Listview item of.</param>
|
/// <param name="client">The client to get the Listview item of.</param>
|
||||||
/// <returns>Listview item of the client.</returns>
|
/// <returns>Listview item of the client.</returns>
|
||||||
private ListViewItem GetListViewItemByClient(Client c)
|
private ListViewItem GetListViewItemByClient(Client client)
|
||||||
{
|
{
|
||||||
|
if (client == null) return null;
|
||||||
|
|
||||||
ListViewItem itemClient = null;
|
ListViewItem itemClient = null;
|
||||||
|
|
||||||
lstClients.Invoke((MethodInvoker) delegate
|
lstClients.Invoke((MethodInvoker) delegate
|
||||||
{
|
{
|
||||||
itemClient = lstClients.Items.Cast<ListViewItem>()
|
itemClient = lstClients.Items.Cast<ListViewItem>()
|
||||||
.FirstOrDefault(lvi => lvi != null && c.Equals(lvi.Tag));
|
.FirstOrDefault(lvi => lvi != null && client.Equals(lvi.Tag));
|
||||||
});
|
});
|
||||||
|
|
||||||
return itemClient;
|
return itemClient;
|
||||||
|
@ -309,8 +386,8 @@ namespace xServer.Forms
|
||||||
if (lstClients.SelectedItems.Count == 0) return;
|
if (lstClients.SelectedItems.Count == 0) return;
|
||||||
clients.AddRange(
|
clients.AddRange(
|
||||||
lstClients.SelectedItems.Cast<ListViewItem>()
|
lstClients.SelectedItems.Cast<ListViewItem>()
|
||||||
.Where(lvi => lvi != null && lvi.Tag is Client)
|
.Where(lvi => lvi != null)
|
||||||
.Select(lvi => (Client)lvi.Tag));
|
.Select(lvi => lvi.Tag as Client));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue