in rd-net/RdFramework/Impl/SocketWire.cs [527:611]
public Client(Lifetime lifetime, IScheduler scheduler, IPEndPoint endPoint, string? optId = null) :
base("ClientSocket-"+(optId ?? "<noname>"), lifetime, scheduler)
{
var thread = new Thread(() =>
{
try
{
Log.Verbose("{0} : started", Id);
var lastReportedErrorHash = 0;
while (lifetime.IsAlive)
{
try
{
var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket = s;
SetSocketOptions(s);
Log.Verbose("{0}: connecting to {1}.", Id, endPoint);
s.Connect(endPoint);
lock (Lock)
{
if (!lifetime.IsAlive)
{
Log.Verbose("{0} : connected, but lifetime is already canceled, closing socket", Id);
CloseSocket(s); //to guarantee socket termination
return;
}
else
{
Log.Verbose("{0} : connected", Id);
}
}
SocketProvider.Value = Socket;
}
catch (SocketException ex)
{
var errorHashCode = (ex.Message?.GetHashCode() ?? 0) ^ (ex.StackTrace?.GetHashCode() ?? 0);
if (lastReportedErrorHash != errorHashCode)
{
lastReportedErrorHash = errorHashCode;
if (Log.IsVersboseEnabled())
Log.Verbose(ex, $"{Id}: connection error for endpoint \"{endPoint}\".");
}
else
{
Log.Verbose("{0}: connection error for endpoint \"{1}\" ({2}).", Id, endPoint, ex.Message);
}
lock (Lock)
{
if (!lifetime.IsAlive) break;
Monitor.Wait(Lock, TimeoutMs);
if (!lifetime.IsAlive) break;
}
}
}
}
catch (SocketException e)
{
Log.Verbose("{0}: SocketException with message {1}", Id, e.Message);
}
catch (ObjectDisposedException e)
{
Log.Verbose("{0}: ObjectDisposedException with message {1}", Id, e.Message);
}
catch (Exception e)
{
Log.Error(e, Id);
}
finally
{
Log.Verbose("{0}: terminated.", Id);
}
}) {Name = Id+"-Receiver", IsBackground = true};
thread.Start();
AddTerminationActions(thread);
}