From 1d24a48ac28f8d9e645a49f0b3a52296c5df1836 Mon Sep 17 00:00:00 2001 From: "a.bozhenov" Date: Fri, 16 Aug 2019 21:01:11 +0300 Subject: [PATCH] discovery refactoring --- TestApp/MyService.cs | 8 + ZeroLevel.Discovery/DiscoveryService.cs | 11 +- ZeroLevel.Discovery/RouteTable.cs | 225 ------------------ ZeroLevel.Discovery/ServiceEndpointsTable.cs | 130 ++++++++++ ZeroLevel/Models/ZeroServiceInfo.cs | 12 +- ZeroLevel/Services/Network/BaseSocket.cs | 2 +- ZeroLevel/Services/Network/Exchange.cs | 53 ++--- .../Network/Model/SDL/ServiceDescription.cs | 2 +- .../Network/Model/ServiceEndpointInfo.cs | 12 +- .../Network/Model/ServiceEndpointsInfo.cs | 58 ----- .../Network/Model/ServiceRegisterInfo.cs | 41 ++++ ZeroLevel/Services/Network/SocketClient.cs | 28 +++ ZeroLevel/Services/Network/Utils/NetUtils.cs | 1 + ZeroNetworkMonitor/ServiceControlPanel.xaml | 8 +- .../ServiceControlPanel.xaml.cs | 22 +- 15 files changed, 266 insertions(+), 347 deletions(-) delete mode 100644 ZeroLevel.Discovery/RouteTable.cs create mode 100644 ZeroLevel.Discovery/ServiceEndpointsTable.cs delete mode 100644 ZeroLevel/Services/Network/Model/ServiceEndpointsInfo.cs create mode 100644 ZeroLevel/Services/Network/Model/ServiceRegisterInfo.cs diff --git a/TestApp/MyService.cs b/TestApp/MyService.cs index 543cb4b..209f9fe 100644 --- a/TestApp/MyService.cs +++ b/TestApp/MyService.cs @@ -3,6 +3,7 @@ using System.Net; using System.Threading; using ZeroLevel; using ZeroLevel.Network; +using ZeroLevel.Network.SDL; using ZeroLevel.Services.Applications; namespace TestApp @@ -17,6 +18,13 @@ namespace TestApp protected override void StartAction() { + var client = Exchange.GetConnection("192.168.51.104:50223"); + client?.Request("__service_description__", record => + { + Log.Info(record.ServiceInfo.ServiceKey); + }); + return; + Log.Info("Started"); ReadServiceInfo(); var host = UseHost(8800); diff --git a/ZeroLevel.Discovery/DiscoveryService.cs b/ZeroLevel.Discovery/DiscoveryService.cs index bac0b57..c51c805 100644 --- a/ZeroLevel.Discovery/DiscoveryService.cs +++ b/ZeroLevel.Discovery/DiscoveryService.cs @@ -1,4 +1,5 @@ -using ZeroLevel.Models; +using System.Linq; +using ZeroLevel.Models; using ZeroLevel.Network; using ZeroLevel.Services.Applications; @@ -8,6 +9,7 @@ namespace ZeroLevel.Discovery : BaseZeroService { private IRouter _exInbox; + private ServiceEndpointsTable _table; public DiscoveryService() : base("Discovery") @@ -16,12 +18,11 @@ namespace ZeroLevel.Discovery protected override void StartAction() { - var routeTable = new RouteTable(); - Injector.Default.Register(routeTable); + _table = new ServiceEndpointsTable(); var servicePort = Configuration.Default.First("port"); _exInbox = UseHost(servicePort); - _exInbox.RegisterInbox("services", (_) => routeTable.Get()); - _exInbox.RegisterInbox("register", (client, info) => routeTable.Append(info, client)); + _exInbox.RegisterInbox("services", (_) => _table.GetRoutingTable().ToList()); + _exInbox.RegisterInbox("register", (client, info) => _table.AppendOrUpdate(info, client)); } protected override void StopAction() diff --git a/ZeroLevel.Discovery/RouteTable.cs b/ZeroLevel.Discovery/RouteTable.cs deleted file mode 100644 index 56b299a..0000000 --- a/ZeroLevel.Discovery/RouteTable.cs +++ /dev/null @@ -1,225 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using ZeroLevel.Models; -using ZeroLevel.Network; - -namespace ZeroLevel.Discovery -{ - public class RouteTable - : IDisposable - { - private readonly Dictionary _table = new Dictionary(); - private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - - public RouteTable() - { - Load(); - Sheduller.RemindEvery(TimeSpan.FromSeconds(10), Heartbeat); - } - - #region Snapshot - - private static readonly object _snapshot_lock = new object(); - - private void Save() - { - string snapshot; - _lock.EnterReadLock(); - try - { - snapshot = JsonConvert.SerializeObject(_table); - } - catch (Exception ex) - { - Log.Error(ex, "Fault make snapshot"); - return; - } - finally - { - _lock.ExitReadLock(); - } - try - { - var snapshot_path = Path.Combine(Configuration.BaseDirectory, "snapshot.snp"); - lock (_snapshot_lock) - { - File.WriteAllText(snapshot_path, snapshot); - } - } - catch (Exception ex) - { - Log.Error(ex, "Fault save shapshot"); - } - } - - private void Load() - { - try - { - var path = Path.Combine(Configuration.BaseDirectory, "snapshot.snp"); - if (File.Exists(path)) - { - var snapshot = File.ReadAllText(path); - if (string.IsNullOrWhiteSpace(snapshot) == false) - { - var restored = JsonConvert.DeserializeObject>(snapshot); - _lock.EnterWriteLock(); - try - { - _table.Clear(); - foreach (var r in restored) - { - _table.Add(r.Key, r.Value); - } - } - finally - { - _lock.ExitWriteLock(); - } - } - } - } - catch (Exception ex) - { - Log.Error(ex, "Fault load snapshot"); - } - } - - #endregion Snapshot - - private void Heartbeat(long taskid) - { - try - { - var removeEntities = new Dictionary>(); - _lock.EnterReadLock(); - try - { - foreach (var pair in _table) - { - var endpointsToRemove = new List(); - foreach (var e in pair.Value.Endpoints) - { - if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(e)) == false) - { - if (false == removeEntities.ContainsKey(pair.Key)) - { - removeEntities.Add(pair.Key, new List()); - } - removeEntities[pair.Key].Add(e); - } - } - } - } - finally - { - _lock.ExitReadLock(); - } - _lock.EnterWriteLock(); - try - { - foreach (var pair in removeEntities) - { - foreach (var ep in pair.Value) - { - _table[pair.Key].Endpoints.Remove(ep); - Log.Debug($"Removed address {ep}"); - } - } - var badKeys = _table.Where(f => f.Value.Endpoints.Count == 0) - .Select(pair => pair.Key) - .ToList(); - foreach (var badKey in badKeys) - { - _table.Remove(badKey); - Log.Debug($"Removed service {badKey}"); - } - } - finally - { - _lock.ExitWriteLock(); - } - } - catch (Exception ex) - { - Log.Error(ex, "Fault heartbeat"); - } - Save(); - } - - public InvokeResult Append(ZeroServiceInfo serviceInfo, ISocketClient client) - { - InvokeResult result = null; - var endpoint = $"{client.Endpoint.Address}:{serviceInfo.Port}"; - Log.Info($"Regiter request from {endpoint}. Service {serviceInfo?.ServiceKey}"); - if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(endpoint))) - { - var key = $"{serviceInfo.ServiceGroup}:{serviceInfo.ServiceType}:{serviceInfo.ServiceKey.Trim().ToLowerInvariant()}"; - _lock.EnterWriteLock(); - try - { - if (false == _table.ContainsKey(key)) - { - _table.Add(key, new ServiceEndpointsInfo - { - ServiceKey = serviceInfo.ServiceKey, - Version = serviceInfo.Version, - ServiceGroup = serviceInfo.ServiceGroup, - ServiceType = serviceInfo.ServiceType, - Endpoints = new List() - }); - _table[key].Endpoints.Add(endpoint); - Log.Info($"The service '{serviceInfo.ServiceKey}' registered on endpoint: {endpoint}"); - } - else - { - var exists = _table[key]; - if (exists.Endpoints.Contains(endpoint) == false) - { - Log.Info($"The service '{serviceInfo.ServiceKey}' register endpoint: {endpoint}"); - exists.Endpoints.Add(endpoint); - } - } - } - catch (Exception ex) - { - Log.Error(ex, $"Fault append service ({serviceInfo.ServiceKey} {serviceInfo.Version}) endpoint '{endpoint}'"); - result = InvokeResult.Fault(ex.Message); - } - finally - { - _lock.ExitWriteLock(); - } - Save(); - result = InvokeResult.Succeeding(); - } - else - { - result = InvokeResult.Fault($"Appending endpoint '{endpoint}' canceled for service {serviceInfo.ServiceKey} ({serviceInfo.Version}) because endpoind no avaliable"); - } - return result; - } - - public IEnumerable Get() - { - _lock.EnterReadLock(); - try - { - return _table.Values.ToList(); - } - finally - { - _lock.ExitReadLock(); - } - } - - public void Dispose() - { - _lock.Dispose(); - } - } -} \ No newline at end of file diff --git a/ZeroLevel.Discovery/ServiceEndpointsTable.cs b/ZeroLevel.Discovery/ServiceEndpointsTable.cs new file mode 100644 index 0000000..09e10f6 --- /dev/null +++ b/ZeroLevel.Discovery/ServiceEndpointsTable.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using ZeroLevel.Models; +using ZeroLevel.Network; +using ZeroLevel.Services.Serialization; + +namespace ZeroLevel.Discovery +{ + public class ServiceEndpointsTable + { + private ConcurrentDictionary _records; + + public ServiceEndpointsTable() + { + if (!TryLoad()) + { + _records = new ConcurrentDictionary(); + } + Sheduller.RemindEvery(TimeSpan.FromSeconds(10), Heartbeat); + } + + public InvokeResult AppendOrUpdate(ServiceRegisterInfo registerInfo, ISocketClient client) + { + if (registerInfo == null || registerInfo.ServiceInfo == null) return InvokeResult.Fault(); + + var endpoint = $"{client.Endpoint.Address}:{registerInfo.Port}"; + Log.Info($"[ServiceEndpointsTable.AppendOrUpdate]\t{registerInfo.ServiceInfo.ServiceKey}\t{endpoint}"); + if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(endpoint))) + { + _records.AddOrUpdate(endpoint, registerInfo.ServiceInfo, (key, oldValue) => registerInfo.ServiceInfo); + Save(); + return InvokeResult.Succeeding(); + } + else + { + Log.Warning($"[ServiceEndpointsTable.AppendOrUpdate]\t{registerInfo.ServiceInfo.ServiceKey}\t{endpoint} no avaliable"); + } + return InvokeResult.Fault(); + } + + public IEnumerable GetRoutingTable() + { + foreach (var pair in _records) yield return new ServiceEndpointInfo { Endpoint = pair.Key, ServiceInfo = pair.Value }; + } + + #region Snapshot + private void Save() + { + try + { + using (var fs = new FileStream(Path.Combine(Configuration.BaseDirectory, "snapshot.snp") + , FileMode.Create + , FileAccess.Write + , FileShare.None)) + { + using (var writer = new MemoryStreamWriter(fs)) + { + writer.WriteDictionary(_records); + writer.Stream.Flush(); + } + } + } + catch (Exception ex) + { + Log.Error(ex, "[ServiceEndpointsTable.Save]"); + } + } + + private bool TryLoad() + { + try + { + var path = Path.Combine(Configuration.BaseDirectory, "snapshot.snp"); + if (File.Exists(path)) + { + using (var fs = new FileStream(path + , FileMode.Open + , FileAccess.Read + , FileShare.None)) + { + using (var reader = new MemoryStreamReader(fs)) + { + _records = reader.ReadDictionaryAsConcurrent(); + return _records != null; + } + } + } + } + catch (Exception ex) + { + Log.Error(ex, "[ServiceEndpointsTable.Load]"); + } + return false; + } + + #endregion Snapshot + + #region Heartbeat + private void Heartbeat(long taskid) + { + try + { + var toRemove = new List(); + foreach (var pair in _records) + { + if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(pair.Key)) == false) + { + toRemove.Add(pair.Key); + } + } + ZeroServiceInfo service; + foreach (var key in toRemove) + { + if (_records.TryRemove(key, out service)) + { + Log.Info($"[ServiceEndpointsTable.Heartbeat] {service.ServiceKey} on {key} was removed because not answer for ping"); + } + } + } + catch (Exception ex) + { + Log.Error(ex, $"[ServiceEndpointsTable.Heartbeat]"); + } + Save(); + } + #endregion + } +} diff --git a/ZeroLevel/Models/ZeroServiceInfo.cs b/ZeroLevel/Models/ZeroServiceInfo.cs index 98f18ca..f6de918 100644 --- a/ZeroLevel/Models/ZeroServiceInfo.cs +++ b/ZeroLevel/Models/ZeroServiceInfo.cs @@ -38,20 +38,12 @@ namespace ZeroLevel /// [DataMember] public string Version { get; set; } - /// - /// Service port - /// - /// TODO move port out to new class for discovery service - /// - /// - [DataMember] - public int Port { get; set; } + public bool Equals(ZeroServiceInfo other) { if (other == null) return false; if (object.ReferenceEquals(this, other)) return true; - if (this.Port != other.Port) return false; if (string.Compare(this.Name, other.Name, true) != 0) return false; if (string.Compare(this.ServiceKey, other.ServiceKey, true) != 0) return false; if (string.Compare(this.ServiceGroup, other.ServiceGroup, true) != 0) return false; @@ -72,7 +64,6 @@ namespace ZeroLevel public void Serialize(IBinaryWriter writer) { - writer.WriteInt32(this.Port); writer.WriteString(this.Name); writer.WriteString(this.ServiceKey); writer.WriteString(this.ServiceGroup); @@ -82,7 +73,6 @@ namespace ZeroLevel public void Deserialize(IBinaryReader reader) { - this.Port = reader.ReadInt32(); this.Name = reader.ReadString(); this.ServiceKey = reader.ReadString(); this.ServiceGroup = reader.ReadString(); diff --git a/ZeroLevel/Services/Network/BaseSocket.cs b/ZeroLevel/Services/Network/BaseSocket.cs index 70e765a..de24b00 100644 --- a/ZeroLevel/Services/Network/BaseSocket.cs +++ b/ZeroLevel/Services/Network/BaseSocket.cs @@ -49,7 +49,7 @@ namespace ZeroLevel.Network /// /// The size of the message queue to send /// - public const int MAX_SEND_QUEUE_SIZE = 1024; + public const int MAX_SEND_QUEUE_SIZE = 256; protected void Broken() => Status = Status == SocketClientStatus.Disposed ? Status : SocketClientStatus.Broken; protected void Disposed() => Status = SocketClientStatus.Disposed; diff --git a/ZeroLevel/Services/Network/Exchange.cs b/ZeroLevel/Services/Network/Exchange.cs index 95bef67..7931070 100644 --- a/ZeroLevel/Services/Network/Exchange.cs +++ b/ZeroLevel/Services/Network/Exchange.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using ZeroLevel.Models; using ZeroLevel.Network.SDL; -using ZeroLevel.Services.Serialization; namespace ZeroLevel.Network { @@ -521,23 +520,21 @@ namespace ZeroLevel.Network var discoveryClient = _cachee.GetClient(discovery_endpoint.Value, true); if (discoveryClient != null) { - var services = _cachee.ServerList. - Select(s => - { - var info = MessageSerializer.Copy(_owner.ServiceInfo); - info.Port = s.LocalEndpoint.Port; - return info; - }). - ToList(); - foreach (var service in services) + foreach (var service in _cachee.ServerList) { - var request = discoveryClient.Request("register", service, r => - { - if (!r.Success) + var request = discoveryClient.Request("register" + , new ServiceRegisterInfo { - Log.SystemWarning($"[Exchange.RegisterServicesInDiscovery] Register canceled. {r.Comment}"); + Port = service.LocalEndpoint.Port, + ServiceInfo = _owner.ServiceInfo } - }); + , r => + { + if (!r.Success) + { + Log.SystemWarning($"[Exchange.RegisterServicesInDiscovery] Register canceled. {r.Comment}"); + } + }); if (request.Success == false) { Log.SystemWarning($"[Exchange.RegisterServicesInDiscovery] Register canceled.{request.Comment}"); @@ -557,36 +554,22 @@ namespace ZeroLevel.Network { try { - var ir = discoveryClient.Request>("services", records => + var ir = discoveryClient.Request>("services", records => { if (records == null) { Log.SystemWarning("[Exchange.UpdateServiceListFromDiscovery] UpdateServiceListInfo. Discrovery response is empty"); return; } - var endpoints = new HashSet(); _dicovery_aliases.BeginUpdate(); try { foreach (var service in records) { - endpoints.Clear(); - foreach (var ep in service.Endpoints) - { - try - { - var endpoint = NetUtils.CreateIPEndPoint(ep); - endpoints.Add(endpoint); - } - catch - { - Log.SystemWarning($"[Exchange.UpdateServiceListFromDiscovery] Can't parse address {ep} as IPEndPoint"); - } - } - _dicovery_aliases.Set(service.ServiceKey, - service.ServiceType, - service.ServiceGroup, - endpoints); + _dicovery_aliases.Set(service.ServiceInfo.ServiceKey + , service.ServiceInfo.ServiceType + , service.ServiceInfo.ServiceGroup + , NetUtils.CreateIPEndPoint(service.Endpoint)); } _dicovery_aliases.Commit(); } @@ -997,7 +980,7 @@ namespace ZeroLevel.Network { i.Port = se.LocalEndpoint.Port; return i; - })) + })).ToList() }; } diff --git a/ZeroLevel/Services/Network/Model/SDL/ServiceDescription.cs b/ZeroLevel/Services/Network/Model/SDL/ServiceDescription.cs index cb3bf81..dc423a3 100644 --- a/ZeroLevel/Services/Network/Model/SDL/ServiceDescription.cs +++ b/ZeroLevel/Services/Network/Model/SDL/ServiceDescription.cs @@ -7,7 +7,7 @@ namespace ZeroLevel.Network.SDL : IBinarySerializable { public ZeroServiceInfo ServiceInfo { get; set; } - public IEnumerable Inboxes { get; set; } + public List Inboxes { get; set; } public void Deserialize(IBinaryReader reader) { diff --git a/ZeroLevel/Services/Network/Model/ServiceEndpointInfo.cs b/ZeroLevel/Services/Network/Model/ServiceEndpointInfo.cs index 0a8c890..0973122 100644 --- a/ZeroLevel/Services/Network/Model/ServiceEndpointInfo.cs +++ b/ZeroLevel/Services/Network/Model/ServiceEndpointInfo.cs @@ -7,18 +7,16 @@ namespace ZeroLevel.Network /// Endpoint /// public class ServiceEndpointInfo : - IEquatable + IBinarySerializable, IEquatable { - public string Key { get; set; } - public string Type { get; set; } - public string Group { get; set; } public string Endpoint { get; set; } + public ZeroServiceInfo ServiceInfo { get; set; } public bool Equals(ServiceEndpointInfo other) { if (other == null) return false; if (string.Compare(this.Endpoint, other.Endpoint, true) != 0) return false; - return true; + return this.ServiceInfo?.Equals(other.ServiceInfo) ?? other != null ? false : true; } public override bool Equals(object obj) @@ -28,17 +26,19 @@ namespace ZeroLevel.Network public override int GetHashCode() { - return Endpoint?.GetHashCode() ?? 0; + return this.ServiceInfo?.GetHashCode() ?? 0 ^ Endpoint?.GetHashCode() ?? 0; } public void Serialize(IBinaryWriter writer) { writer.WriteString(this.Endpoint); + writer.Write(this.ServiceInfo); } public void Deserialize(IBinaryReader reader) { this.Endpoint = reader.ReadString(); + this.ServiceInfo = reader.Read(); } } } \ No newline at end of file diff --git a/ZeroLevel/Services/Network/Model/ServiceEndpointsInfo.cs b/ZeroLevel/Services/Network/Model/ServiceEndpointsInfo.cs deleted file mode 100644 index b90f4a6..0000000 --- a/ZeroLevel/Services/Network/Model/ServiceEndpointsInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using ZeroLevel.Services.Serialization; - -namespace ZeroLevel.Network -{ - /// - /// Information about service connection points - /// - public class ServiceEndpointsInfo : - IEquatable, IBinarySerializable - { - public string ServiceKey { get; set; } - public string Version { get; set; } - public string ServiceGroup { get; set; } - public string ServiceType { get; set; } - public List Endpoints { get; set; } - - public bool Equals(ServiceEndpointsInfo other) - { - if (other == null) return false; - if (string.Compare(this.ServiceKey, other.ServiceKey, true) != 0) return false; - if (string.Compare(this.Version, other.Version, true) != 0) return false; - if (string.Compare(this.ServiceGroup, other.ServiceGroup, true) != 0) return false; - if (string.Compare(this.ServiceType, other.ServiceType, true) != 0) return false; - if (!CollectionComparsionExtensions.NoOrderingEquals(this.Endpoints, other.Endpoints, (a, b) => a.Equals(b))) return false; - return true; - } - - public override bool Equals(object obj) - { - return this.Equals(obj as ServiceEndpointsInfo); - } - - public override int GetHashCode() - { - return ServiceKey?.GetHashCode() ?? 0 ^ Version?.GetHashCode() ?? 0 ^ ServiceGroup?.GetHashCode() ?? 0 ^ ServiceType?.GetHashCode() ?? 0; - } - - public void Serialize(IBinaryWriter writer) - { - writer.WriteString(this.ServiceKey); - writer.WriteString(this.Version); - writer.WriteString(this.ServiceGroup); - writer.WriteString(this.ServiceType); - writer.WriteCollection(this.Endpoints); - } - - public void Deserialize(IBinaryReader reader) - { - this.ServiceKey = reader.ReadString(); - this.Version = reader.ReadString(); - this.ServiceGroup = reader.ReadString(); - this.ServiceType = reader.ReadString(); - this.Endpoints = reader.ReadStringCollection(); - } - } -} \ No newline at end of file diff --git a/ZeroLevel/Services/Network/Model/ServiceRegisterInfo.cs b/ZeroLevel/Services/Network/Model/ServiceRegisterInfo.cs new file mode 100644 index 0000000..035b5a0 --- /dev/null +++ b/ZeroLevel/Services/Network/Model/ServiceRegisterInfo.cs @@ -0,0 +1,41 @@ +using System; +using ZeroLevel.Services.Serialization; + +namespace ZeroLevel.Network +{ + public class ServiceRegisterInfo : + IBinarySerializable, IEquatable + { + public int Port { get; set; } + public ZeroServiceInfo ServiceInfo { get; set; } + + public bool Equals(ServiceRegisterInfo other) + { + if (other == null) return false; + if (this.Port != other.Port) return false; + return this.ServiceInfo?.Equals(other.ServiceInfo) ?? other != null ? false : true; + } + + public override bool Equals(object obj) + { + return this.Equals(obj as ServiceRegisterInfo); + } + + public override int GetHashCode() + { + return Port.GetHashCode() ^ this.ServiceInfo.GetHashCode(); + } + + public void Serialize(IBinaryWriter writer) + { + writer.WriteInt32(this.Port); + writer.Write(this.ServiceInfo); + } + + public void Deserialize(IBinaryReader reader) + { + this.Port = reader.ReadInt32(); + this.ServiceInfo = reader.Read(); + } + } +} diff --git a/ZeroLevel/Services/Network/SocketClient.cs b/ZeroLevel/Services/Network/SocketClient.cs index a8f70f0..f5317d0 100644 --- a/ZeroLevel/Services/Network/SocketClient.cs +++ b/ZeroLevel/Services/Network/SocketClient.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Net; using System.Net.Sockets; +using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using ZeroLevel.Services; @@ -453,7 +455,33 @@ namespace ZeroLevel.Network s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); return s; } + /* TODO to test + public async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + try + { + // Workaround for: https://github.com/dotnet/corefx/issues/24430 + using (cancellationToken.Register(Dispose)) + { + if (cancellationToken.IsCancellationRequested) + { + return 0; + } + + return await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); + } + } + catch (IOException exception) + { + if (exception.InnerException is SocketException socketException) + { + ExceptionDispatchInfo.Capture(socketException).Throw(); + } + throw; + } + } + */ #endregion Helper public override void Dispose() diff --git a/ZeroLevel/Services/Network/Utils/NetUtils.cs b/ZeroLevel/Services/Network/Utils/NetUtils.cs index d43a286..c1b590c 100644 --- a/ZeroLevel/Services/Network/Utils/NetUtils.cs +++ b/ZeroLevel/Services/Network/Utils/NetUtils.cs @@ -26,6 +26,7 @@ namespace ZeroLevel.Network try { socket.Connect(endpoint); + socket.Shutdown(SocketShutdown.Both); socket.Close(); return true; } diff --git a/ZeroNetworkMonitor/ServiceControlPanel.xaml b/ZeroNetworkMonitor/ServiceControlPanel.xaml index 0da8e3e..e25d210 100644 --- a/ZeroNetworkMonitor/ServiceControlPanel.xaml +++ b/ZeroNetworkMonitor/ServiceControlPanel.xaml @@ -10,6 +10,7 @@ + @@ -37,8 +38,9 @@