mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
Updated Telepathy to latest version
This commit is contained in:
parent
f104699784
commit
445e37aed1
@ -7,22 +7,29 @@ namespace Telepathy
|
||||
public class Client : Common
|
||||
{
|
||||
TcpClient client;
|
||||
Thread thread;
|
||||
|
||||
public bool Connecting
|
||||
{
|
||||
get { return thread != null && thread.IsAlive &&
|
||||
client != null && !client.Connected; }
|
||||
}
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return thread != null && thread.IsAlive &&
|
||||
client != null && client.Connected; }
|
||||
get
|
||||
{
|
||||
// TcpClient.Connected doesn't check if socket != null, which
|
||||
// results in NullReferenceExceptions if connection was closed.
|
||||
// -> let's check it manually instead
|
||||
return client != null &&
|
||||
client.Client != null &&
|
||||
client.Client.Connected;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Connecting
|
||||
{
|
||||
// client was created by Connect() call but not fully connected yet?
|
||||
get { return client != null && !Connected; }
|
||||
}
|
||||
|
||||
// the thread function
|
||||
void ThreadFunction(string ip, int port)
|
||||
// (static to reduce state for maximum reliability)
|
||||
static void ThreadFunction(TcpClient client, string ip, int port, SafeQueue<Message> messageQueue)
|
||||
{
|
||||
// absolutely must wrap with try/catch, otherwise thread
|
||||
// exceptions are silent
|
||||
@ -34,7 +41,7 @@ void ThreadFunction(string ip, int port)
|
||||
client.Connect(ip, port);
|
||||
|
||||
// run the receive loop
|
||||
ReceiveLoop(0, client);
|
||||
ReceiveLoop(0, client, messageQueue);
|
||||
}
|
||||
catch (SocketException exception)
|
||||
{
|
||||
@ -45,15 +52,17 @@ void ThreadFunction(string ip, int port)
|
||||
// add 'Disconnected' event to message queue so that the caller
|
||||
// knows that the Connect failed. otherwise they will never know
|
||||
messageQueue.Enqueue(new Message(0, EventType.Disconnected, null));
|
||||
|
||||
// clean up properly before exiting
|
||||
client.Close();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// something went wrong. probably important.
|
||||
Logger.LogError("Client Exception: " + exception);
|
||||
}
|
||||
|
||||
// if we got here then we are done. ReceiveLoop cleans up already,
|
||||
// but we may never get there if connect fails. so let's clean up
|
||||
// here too.
|
||||
client.Close();
|
||||
}
|
||||
|
||||
public void Connect(string ip, int port)
|
||||
@ -77,7 +86,7 @@ public void Connect(string ip, int port)
|
||||
// too long, which is especially good in games
|
||||
// -> this way we don't async client.BeginConnect, which seems to
|
||||
// fail sometimes if we connect too many clients too fast
|
||||
thread = new Thread(() => { ThreadFunction(ip, port); });
|
||||
Thread thread = new Thread(() => { ThreadFunction(client, ip, port, messageQueue); });
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
}
|
||||
@ -85,16 +94,23 @@ public void Connect(string ip, int port)
|
||||
public void Disconnect()
|
||||
{
|
||||
// only if started
|
||||
if (!Connecting && !Connected) return;
|
||||
if (Connecting || Connected)
|
||||
{
|
||||
// close client, ThreadFunc will end and clean up
|
||||
client.Close();
|
||||
|
||||
Logger.Log("Client: disconnecting");
|
||||
// clear client reference so that we can call Connect again
|
||||
// immediately after calling Disconnect.
|
||||
// -> this client's thread will end in the background in a few
|
||||
// milliseconds, we don't need to worry about it anymore
|
||||
// -> setting it null here won't set it null in ThreadFunction,
|
||||
// because it's static and we pass a reference. so there
|
||||
// won't be any NullReferenceExceptions. the thread will just
|
||||
// end gracefully.
|
||||
client = null;
|
||||
|
||||
// this is supposed to disconnect gracefully, but the blocking Read
|
||||
// calls throw a 'Read failure' exception instead of returning 0.
|
||||
// (maybe it's Unity? maybe Mono?)
|
||||
client.GetStream().Close();
|
||||
client.Close();
|
||||
client = null;
|
||||
Logger.Log("Client: disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
public bool Send(byte[] data)
|
||||
|
@ -18,13 +18,14 @@ public abstract class Common
|
||||
// - 100k messages are 1.95MB
|
||||
// 2MB are not that much, but it is a bad sign if the caller process
|
||||
// can't call GetNextMessage faster than the incoming messages.
|
||||
public int messageQueueSizeWarning = 100000;
|
||||
DateTime messageQueueLastWarning = DateTime.Now;
|
||||
public static int messageQueueSizeWarning = 100000;
|
||||
|
||||
// removes and returns the oldest message from the message queue.
|
||||
// (might want to call this until it doesn't return anything anymore)
|
||||
// -> Connected, Data, Disconnected events are all added here
|
||||
// -> bool return makes while (GetMessage(out Message)) easier!
|
||||
// -> no 'is client connected' check because we still want to read the
|
||||
// Disconnected message after a disconnect
|
||||
public bool GetNextMessage(out Message message)
|
||||
{
|
||||
return messageQueue.TryDequeue(out message);
|
||||
@ -114,11 +115,15 @@ protected static bool ReadMessageBlocking(NetworkStream stream, out byte[] conte
|
||||
}
|
||||
|
||||
// thread receive function is the same for client and server's clients
|
||||
protected void ReceiveLoop(int connectionId, TcpClient client)
|
||||
// (static to reduce state for maximum reliability)
|
||||
protected static void ReceiveLoop(int connectionId, TcpClient client, SafeQueue<Message> messageQueue)
|
||||
{
|
||||
// get NetworkStream from client
|
||||
NetworkStream stream = client.GetStream();
|
||||
|
||||
// keep track of last message queue warning
|
||||
DateTime messageQueueLastWarning = DateTime.Now;
|
||||
|
||||
// absolutely must wrap with try/catch, otherwise thread exceptions
|
||||
// are silent
|
||||
try
|
||||
|
@ -73,7 +73,7 @@ void Listen(int port, int maxConnections)
|
||||
clients.Add(connectionId, client);
|
||||
|
||||
// run the receive loop
|
||||
ReceiveLoop(connectionId, client);
|
||||
ReceiveLoop(connectionId, client, messageQueue);
|
||||
|
||||
// remove client from clients dict afterwards
|
||||
clients.Remove(connectionId);
|
||||
@ -145,10 +145,9 @@ public void Stop()
|
||||
List<TcpClient> connections = clients.GetValues();
|
||||
foreach (TcpClient client in connections)
|
||||
{
|
||||
// this is supposed to disconnect gracefully, but the blocking
|
||||
// Read calls throw a 'Read failure' exception in Unity
|
||||
// sometimes (instead of returning 0)
|
||||
client.GetStream().Close();
|
||||
// close the stream if not closed yet. it may have been closed
|
||||
// by a disconnect already, so use try/catch
|
||||
try { client.GetStream().Close(); } catch {}
|
||||
client.Close();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user