Mirror/Unity-Technologies-networking/Runtime/Telepathy/Client.cs
2018-08-17 14:07:54 +02:00

100 lines
3.3 KiB
C#

using System;
using System.Net.Sockets;
using System.Threading;
namespace Telepathy
{
public class Client : Common
{
TcpClient client = new TcpClient();
Thread thread;
public bool Connecting
{
get { return thread != null && thread.IsAlive && !client.Connected; }
}
public bool Connected
{
get { return thread != null && thread.IsAlive && client.Connected; }
}
// the thread function
void ThreadFunction(string ip, int port)
{
// absolutely must wrap with try/catch, otherwise thread
// exceptions are silent
try
{
// connect (blocking)
// (NoDelay disables nagle algorithm. lowers CPU% and latency)
client.NoDelay = true;
client.Connect(ip, port);
// run the receive loop
ReceiveLoop(0, client);
}
catch (SocketException exception)
{
// this happens if (for example) the ip address is correct
// but there is no server running on that ip/port
Logger.Log("Client: failed to connect to ip=" + ip + " port=" + port + " reason=" + exception);
// clean up properly before exiting
client.Close();
}
catch (Exception exception)
{
// something went wrong. probably important.
Logger.LogError("Client Exception: " + exception);
}
}
public void Connect(string ip, int port)
{
// not if already started
if (Connecting || Connected) return;
// clear old messages in queue, just to be sure that the caller
// doesn't receive data from last time and gets out of sync.
// -> calling this in Disconnect isn't smart because the caller may
// still want to process all the latest messages afterwards
messageQueue.Clear();
// client.Connect(ip, port) is blocking. let's call it in the thread
// and return immediately.
// -> this way the application doesn't hang for 30s if connect takes
// 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.IsBackground = true;
thread.Start();
}
public void Disconnect()
{
// only if started
if (!Connecting && !Connected) return;
Logger.Log("Client: disconnecting");
// 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();
}
public bool Send(byte[] data)
{
if (Connected)
{
return SendMessage(client.GetStream(), data);
}
Logger.LogWarning("Client.Send: not connected!");
return false;
}
}
}