diff --git a/SimpleTCP/Message.cs b/SimpleTCP/Message.cs index d9d9a6a..71a155b 100644 --- a/SimpleTCP/Message.cs +++ b/SimpleTCP/Message.cs @@ -1,72 +1,62 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Net.Sockets; using System.Text; -using System.Threading.Tasks; namespace SimpleTCP { public class Message { - private TcpClient _tcpClient; - private System.Text.Encoding _encoder = null; - private byte _writeLineDelimiter; - private bool _autoTrim = false; - internal Message(byte[] data, TcpClient tcpClient, System.Text.Encoding stringEncoder, byte lineDelimiter) + private readonly Encoding _encoder; + private readonly byte _writeLineDelimiter; + private readonly bool _autoTrim; + + public byte[] Data { get; } + public TcpClient TcpClient { get; } + public string MessageString => _autoTrim ? _encoder.GetString(Data).Trim() : _encoder.GetString(Data); + + + internal Message(byte[] data, TcpClient tcpClient, Encoding stringEncoder, byte lineDelimiter) { Data = data; - _tcpClient = tcpClient; + TcpClient = tcpClient; _encoder = stringEncoder; _writeLineDelimiter = lineDelimiter; } - internal Message(byte[] data, TcpClient tcpClient, System.Text.Encoding stringEncoder, byte lineDelimiter, bool autoTrim) + internal Message(byte[] data, TcpClient tcpClient, Encoding stringEncoder, byte lineDelimiter, bool autoTrim) { Data = data; - _tcpClient = tcpClient; + TcpClient = tcpClient; _encoder = stringEncoder; _writeLineDelimiter = lineDelimiter; _autoTrim = autoTrim; } - public byte[] Data { get; private set; } - public string MessageString - { - get - { - if (_autoTrim) - { - return _encoder.GetString(Data).Trim(); - } - - return _encoder.GetString(Data); - } - } - public void Reply(byte[] data) { - _tcpClient.GetStream().Write(data, 0, data.Length); + TcpClient.GetStream().Write(data, 0, data.Length); } public void Reply(string data) { - if (string.IsNullOrEmpty(data)) { return; } + if (string.IsNullOrEmpty(data)) + return; + Reply(_encoder.GetBytes(data)); } public void ReplyLine(string data) { - if (string.IsNullOrEmpty(data)) { return; } + if (string.IsNullOrEmpty(data)) + return; + if (data.LastOrDefault() != _writeLineDelimiter) { - Reply(data + _encoder.GetString(new byte[] { _writeLineDelimiter })); - } else - { - Reply(data); + Reply(data + _encoder.GetString(new[] { _writeLineDelimiter })); + return; } - } - public TcpClient TcpClient { get { return _tcpClient; } } + Reply(data); + } } } diff --git a/SimpleTCP/Server/ConnectedClient.cs b/SimpleTCP/Server/ConnectedClient.cs index c1704a2..c1857e8 100644 --- a/SimpleTCP/Server/ConnectedClient.cs +++ b/SimpleTCP/Server/ConnectedClient.cs @@ -1,16 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; +using System.Net; using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -namespace SimpleTCP +namespace SimpleTCP.Server { public class ConnectedClient { - public IPAddress ServerIP { get; internal set; } + public IPAddress ServerIp { get; internal set; } public TcpClient Client { get; internal set; } } } diff --git a/SimpleTCP/Server/ServerListener.cs b/SimpleTCP/Server/ServerListener.cs index 7f39d97..dfecd31 100644 --- a/SimpleTCP/Server/ServerListener.cs +++ b/SimpleTCP/Server/ServerListener.cs @@ -1,63 +1,43 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Net; using System.Net.Sockets; -using System.Text; using System.Threading; -using System.Threading.Tasks; namespace SimpleTCP.Server { internal class ServerListener { - private TcpListenerEx _listener = null; - private List _connectedClients = new List(); - private List _disconnectedClients = new List(); - private SimpleTcpServer _parent = null; - private List _queuedMsg = new List(); + private readonly List _connectedClients = new List(); + private readonly List _disconnectedClients = new List(); + private readonly SimpleTcpServer _parent; + private readonly List _queuedMsg = new List(); private byte _delimiter = 0x13; - private Thread _rxThread = null; + private Thread _rxThread; - public int ConnectedClientsCount - { - get { return _connectedClients.Count; } - } + public int ConnectedClientsCount => _connectedClients.Count; + public IEnumerable ConnectedClients => _connectedClients; - public IEnumerable ConnectedClients { get { return _connectedClients; } } + internal bool QueueStop { get; set; } + internal IPAddress IpAddress { get; } + internal int Port { get; } + internal int ReadLoopIntervalMs { get; set; } + internal TcpListenerEx Listener { get; } internal ServerListener(SimpleTcpServer parentServer, IPAddress ipAddress, int port) { QueueStop = false; _parent = parentServer; - IPAddress = ipAddress; + IpAddress = ipAddress; Port = port; ReadLoopIntervalMs = 10; - _listener = new TcpListenerEx(ipAddress, port); - _listener.Start(); + Listener = new TcpListenerEx(ipAddress, port); + Listener.Start(); - System.Threading.ThreadPool.QueueUserWorkItem(ListenerLoop); + ThreadPool.QueueUserWorkItem(ListenerLoop); } - private void StartThread() - { - if (_rxThread != null) { return; } - _rxThread = new Thread(ListenerLoop); - _rxThread.IsBackground = true; - _rxThread.Start(); - } - - internal bool QueueStop { get; set; } - internal IPAddress IPAddress { get; private set; } - internal int Port { get; private set; } - internal int ReadLoopIntervalMs { get; set; } - - internal TcpListenerEx Listener { get { return _listener; } } - - - - private void ListenerLoop(object state) + private void ListenerLoop(object state) { while (!QueueStop) { @@ -65,29 +45,24 @@ private void ListenerLoop(object state) { RunLoopStep(); } - catch + catch { } - System.Threading.Thread.Sleep(ReadLoopIntervalMs); + Thread.Sleep(ReadLoopIntervalMs); } - _listener.Stop(); + Listener.Stop(); + } + + private static bool IsSocketConnected(Socket s) + { + // https://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c + var part1 = s.Poll(1000, SelectMode.SelectRead); + var part2 = (s.Available == 0); + return (!part1 || !part2) && s.Connected; } - - bool IsSocketConnected(Socket s) - { - // https://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c - bool part1 = s.Poll(1000, SelectMode.SelectRead); - bool part2 = (s.Available == 0); - if ((part1 && part2) || !s.Connected) - return false; - else - return true; - } - - private void RunLoopStep() { if (_disconnectedClients.Count > 0) @@ -102,44 +77,45 @@ private void RunLoopStep() } } - if (_listener.Pending()) + if (Listener.Pending()) { - var newClient = _listener.AcceptTcpClient(); - _connectedClients.Add(newClient); + var newClient = Listener.AcceptTcpClient(); + _connectedClients.Add(newClient); _parent.NotifyClientConnected(this, newClient); } - + _delimiter = _parent.Delimiter; - foreach (var c in _connectedClients) + foreach (var client in _connectedClients) { - - if ( IsSocketConnected(c.Client) == false) + + if (IsSocketConnected(client.Client) == false) { - _disconnectedClients.Add(c); + _disconnectedClients.Add(client); } - - int bytesAvailable = c.Available; + + var bytesAvailable = client.Available; if (bytesAvailable == 0) { //Thread.Sleep(10); continue; } - List bytesReceived = new List(); + var bytesReceived = new List(); - while (c.Available > 0 && c.Connected) + while (client.Available > 0 && client.Connected) { - byte[] nextByte = new byte[1]; - c.Client.Receive(nextByte, 0, 1, SocketFlags.None); + var nextByte = new byte[1]; + client.Client.Receive(nextByte, 0, 1, SocketFlags.None); bytesReceived.AddRange(nextByte); if (nextByte[0] == _delimiter) { - byte[] msg = _queuedMsg.ToArray(); + var msg = _queuedMsg.ToArray(); _queuedMsg.Clear(); - _parent.NotifyDelimiterMessageRx(this, c, msg); - } else + _parent.NotifyDelimiterMessageRx(this, client, msg); + } + else { _queuedMsg.AddRange(nextByte); } @@ -147,9 +123,17 @@ private void RunLoopStep() if (bytesReceived.Count > 0) { - _parent.NotifyEndTransmissionRx(this, c, bytesReceived.ToArray()); - } + _parent.NotifyEndTransmissionRx(this, client, bytesReceived.ToArray()); + } } } + + //Think this method should be deleted + private void StartThread() + { + if (_rxThread != null) { return; } + _rxThread = new Thread(ListenerLoop) { IsBackground = true }; + _rxThread.Start(); + } } } diff --git a/SimpleTCP/Server/TcpListenerEx.cs b/SimpleTCP/Server/TcpListenerEx.cs index 1811c48..10a3228 100644 --- a/SimpleTCP/Server/TcpListenerEx.cs +++ b/SimpleTCP/Server/TcpListenerEx.cs @@ -1,38 +1,33 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; +using System.Net; using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; namespace SimpleTCP.Server { + /// /// /// Wrapper around TcpListener that exposes the Active property /// See: http://stackoverflow.com/questions/7630094/is-there-a-property-method-for-determining-if-a-tcplistener-is-currently-listeni /// public class TcpListenerEx : TcpListener { + /// /// - /// Initializes a new instance of the class with the specified local endpoint. + /// Initializes a new instance of the class with the specified local endpoint. /// - /// An that represents the local endpoint to which to bind the listener . is null. - public TcpListenerEx(IPEndPoint localEP) : base(localEP) + /// An that represents the local endpoint to which to bind the listener . is null. + public TcpListenerEx(IPEndPoint localEp) : base(localEp) { } + /// /// - /// Initializes a new instance of the class that listens for incoming connection attempts on the specified local IP address and port number. + /// Initializes a new instance of the class that listens for incoming connection attempts on the specified local IP address and port number. /// - /// An that represents the local IP address. The port on which to listen for incoming connection attempts. is null. is not between and . - public TcpListenerEx(IPAddress localaddr, int port) : base(localaddr, port) + /// An that represents the local IP address. The port on which to listen for incoming connection attempts. is null. is not between and . + public TcpListenerEx(IPAddress localAddr, int port) : base(localAddr, port) { } - public new bool Active - { - get { return base.Active; } - } + public new bool Active => base.Active; } } diff --git a/SimpleTCP/SimpleTcpClient.cs b/SimpleTCP/SimpleTcpClient.cs index 5c66a93..afe7e43 100644 --- a/SimpleTCP/SimpleTcpClient.cs +++ b/SimpleTCP/SimpleTcpClient.cs @@ -5,67 +5,67 @@ using System.Net.Sockets; using System.Text; using System.Threading; -using System.Threading.Tasks; namespace SimpleTCP { public class SimpleTcpClient : IDisposable { - public SimpleTcpClient() - { - StringEncoder = System.Text.Encoding.UTF8; - ReadLoopIntervalMs = 10; - Delimiter = 0x13; - } + private Thread _rxThread; + private readonly List _queuedMsg = new List(); - private Thread _rxThread = null; - private List _queuedMsg = new List(); - public byte Delimiter { get; set; } - public System.Text.Encoding StringEncoder { get; set; } - private TcpClient _client = null; + public byte Delimiter { get; set; } + public Encoding StringEncoder { get; set; } + public bool AutoTrimStrings { get; set; } + public TcpClient TcpClient { get; private set; } - public event EventHandler DelimiterDataReceived; - public event EventHandler DataReceived; + internal bool QueueStop { get; set; } + internal int ReadLoopIntervalMs { get; set; } - internal bool QueueStop { get; set; } - internal int ReadLoopIntervalMs { get; set; } - public bool AutoTrimStrings { get; set; } + public event EventHandler DelimiterDataReceived; + public event EventHandler DataReceived; - public SimpleTcpClient Connect(string hostNameOrIpAddress, int port) + public SimpleTcpClient() + { + StringEncoder = Encoding.UTF8; + ReadLoopIntervalMs = 10; + Delimiter = 0x13; + } + + public SimpleTcpClient Connect(string hostNameOrIpAddress, int port) { if (string.IsNullOrEmpty(hostNameOrIpAddress)) { - throw new ArgumentNullException("hostNameOrIpAddress"); + throw new ArgumentNullException(nameof(hostNameOrIpAddress)); } - _client = new TcpClient(); - _client.Connect(hostNameOrIpAddress, port); + TcpClient = new TcpClient(); + TcpClient.Connect(hostNameOrIpAddress, port); StartRxThread(); return this; } - private void StartRxThread() + private void StartRxThread() { - if (_rxThread != null) { return; } + if (_rxThread != null) + return; - _rxThread = new Thread(ListenerLoop); - _rxThread.IsBackground = true; - _rxThread.Start(); + _rxThread = new Thread(ListenerLoop) { IsBackground = true }; + _rxThread.Start(); } - public SimpleTcpClient Disconnect() + public SimpleTcpClient Disconnect() { - if (_client == null) { return this; } - _client.Close(); - _client = null; + if (TcpClient == null) + return this; + + TcpClient.Close(); + TcpClient = null; return this; } - public TcpClient TcpClient { get { return _client; } } - - private void ListenerLoop(object state) + private void ListenerLoop(object state) { while (!QueueStop) { @@ -78,7 +78,7 @@ private void ListenerLoop(object state) } - System.Threading.Thread.Sleep(ReadLoopIntervalMs); + Thread.Sleep(ReadLoopIntervalMs); } _rxThread = null; @@ -86,29 +86,29 @@ private void ListenerLoop(object state) private void RunLoopStep() { - if (_client == null) { return; } - if (_client.Connected == false) { return; } + if (TcpClient == null) { return; } + if (TcpClient.Connected == false) { return; } - var delimiter = this.Delimiter; - var c = _client; + var delimiter = Delimiter; + var c = TcpClient; - int bytesAvailable = c.Available; + var bytesAvailable = c.Available; if (bytesAvailable == 0) { - System.Threading.Thread.Sleep(10); + Thread.Sleep(10); return; } - List bytesReceived = new List(); + var bytesReceived = new List(); while (c.Available > 0 && c.Connected) { - byte[] nextByte = new byte[1]; + var nextByte = new byte[1]; c.Client.Receive(nextByte, 0, 1, SocketFlags.None); bytesReceived.AddRange(nextByte); if (nextByte[0] == delimiter) { - byte[] msg = _queuedMsg.ToArray(); + var msg = _queuedMsg.ToArray(); _queuedMsg.Clear(); NotifyDelimiterMessageRx(c, msg); } @@ -126,59 +126,64 @@ private void RunLoopStep() private void NotifyDelimiterMessageRx(TcpClient client, byte[] msg) { - if (DelimiterDataReceived != null) - { - Message m = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); - DelimiterDataReceived(this, m); - } + if (DelimiterDataReceived == null) + return; + + var message = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); + DelimiterDataReceived(this, message); } private void NotifyEndTransmissionRx(TcpClient client, byte[] msg) { - if (DataReceived != null) - { - Message m = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); - DataReceived(this, m); - } + if (DataReceived == null) + return; + + var message = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); + DataReceived(this, message); } public void Write(byte[] data) { - if (_client == null) { throw new Exception("Cannot send data to a null TcpClient (check to see if Connect was called)"); } - _client.GetStream().Write(data, 0, data.Length); + if (TcpClient == null) + throw new Exception("Cannot send data to a null TcpClient (check to see if Connect was called)"); + + TcpClient.GetStream().Write(data, 0, data.Length); } public void Write(string data) { - if (data == null) { return; } + if (data == null) + return; + Write(StringEncoder.GetBytes(data)); } public void WriteLine(string data) { - if (string.IsNullOrEmpty(data)) { return; } + if (string.IsNullOrEmpty(data)) + return; + if (data.LastOrDefault() != Delimiter) { - Write(data + StringEncoder.GetString(new byte[] { Delimiter })); - } - else - { - Write(data); + Write(data + StringEncoder.GetString(new[] { Delimiter })); + return; } + + Write(data); } public Message WriteLineAndGetReply(string data, TimeSpan timeout) { Message mReply = null; - this.DataReceived += (s, e) => { mReply = e; }; + DataReceived += (s, e) => { mReply = e; }; WriteLine(data); - Stopwatch sw = new Stopwatch(); + var sw = new Stopwatch(); sw.Start(); while (mReply == null && sw.Elapsed < timeout) { - System.Threading.Thread.Sleep(10); + Thread.Sleep(10); } return mReply; @@ -186,33 +191,33 @@ public Message WriteLineAndGetReply(string data, TimeSpan timeout) #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls + private bool _disposedValue; // To detect redundant calls protected virtual void Dispose(bool disposing) { - if (!disposedValue) - { - if (disposing) - { - // TODO: dispose managed state (managed objects). - - } - - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. - QueueStop = true; - if (_client != null) - { - try - { - _client.Close(); - } - catch { } - _client = null; - } - - disposedValue = true; - } + if (_disposedValue) + return; + + if (disposing) + { + // TODO: dispose managed state (managed objects). + + } + + // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. + // TODO: set large fields to null. + QueueStop = true; + if (TcpClient != null) + { + try + { + TcpClient.Close(); + } + catch { } + TcpClient = null; + } + + _disposedValue = true; } // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. diff --git a/SimpleTCP/SimpleTcpServer.cs b/SimpleTCP/SimpleTcpServer.cs index bdafc3e..392521d 100644 --- a/SimpleTCP/SimpleTcpServer.cs +++ b/SimpleTCP/SimpleTcpServer.cs @@ -1,73 +1,55 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; using System.Threading; -using System.Threading.Tasks; +using SimpleTCP.Server; namespace SimpleTCP { public class SimpleTcpServer { - public SimpleTcpServer() - { - Delimiter = 0x13; - StringEncoder = System.Text.Encoding.UTF8; - } + private readonly List _listeners = new List(); - private List _listeners = new List(); public byte Delimiter { get; set; } - public System.Text.Encoding StringEncoder { get; set; } + public Encoding StringEncoder { get; set; } public bool AutoTrimStrings { get; set; } + public int ConnectedClientsCount => _listeners.Sum(l => l.ConnectedClientsCount); + public bool IsStarted => _listeners.Any(l => l.Listener.Active); + public event EventHandler ClientConnected; public event EventHandler ClientDisconnected; public event EventHandler DelimiterDataReceived; public event EventHandler DataReceived; - public IEnumerable GetIPAddresses() - { - List ipAddresses = new List(); - IEnumerable enabledNetInterfaces = NetworkInterface.GetAllNetworkInterfaces() - .Where(nic => nic.OperationalStatus == OperationalStatus.Up); - foreach (NetworkInterface netInterface in enabledNetInterfaces) - { - IPInterfaceProperties ipProps = netInterface.GetIPProperties(); - foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) - { - if (!ipAddresses.Contains(addr.Address)) - { - ipAddresses.Add(addr.Address); - } - } - } - - var ipSorted = ipAddresses.OrderByDescending(ip => RankIpAddress(ip)).ToList(); - return ipSorted; + public SimpleTcpServer() + { + Delimiter = 0x13; + StringEncoder = Encoding.UTF8; } - public List GetListeningIPs() - { - List listenIps = new List(); - foreach (var l in _listeners) - { - if (!listenIps.Contains(l.IPAddress)) - { - listenIps.Add(l.IPAddress); - } - } + public IEnumerable GetIpAddresses() + => NetworkInterface.GetAllNetworkInterfaces() + .Where(nic => nic.OperationalStatus == OperationalStatus.Up) + .SelectMany(i => i.GetIPProperties().UnicastAddresses.Select(a => a.Address)) + .Distinct() + .OrderByDescending(RankIpAddress); + + public IEnumerable GetListeningIPs() + => _listeners + .Select(l => l.IpAddress) + .Distinct() + .OrderByDescending(RankIpAddress); - return listenIps.OrderByDescending(ip => RankIpAddress(ip)).ToList(); - } - public void Broadcast(byte[] data) { - foreach(var client in _listeners.SelectMany(x => x.ConnectedClients)) + foreach (var client in _listeners.SelectMany(x => x.ConnectedClients)) { client.GetStream().Write(data, 0, data.Length); } @@ -75,26 +57,29 @@ public void Broadcast(byte[] data) public void Broadcast(string data) { - if (data == null) { return; } + if (data == null) + return; + Broadcast(StringEncoder.GetBytes(data)); } public void BroadcastLine(string data) { - if (string.IsNullOrEmpty(data)) { return; } + if (string.IsNullOrEmpty(data)) + return; + if (data.LastOrDefault() != Delimiter) { - Broadcast(data + StringEncoder.GetString(new byte[] { Delimiter })); - } - else - { - Broadcast(data); + Broadcast(data + StringEncoder.GetString(new[] { Delimiter })); + return; } + + Broadcast(data); } - private int RankIpAddress(IPAddress addr) + public int RankIpAddress(IPAddress addr) { - int rankScore = 1000; + var rankScore = 1000; if (IPAddress.IsLoopback(addr)) { @@ -112,45 +97,33 @@ private int RankIpAddress(IPAddress addr) } } - if (rankScore > 500) + if (rankScore <= 500) + return rankScore; + + foreach (var nic in TryGetCurrentNetworkInterfaces()) { - foreach (var nic in TryGetCurrentNetworkInterfaces()) + var ipProps = nic.GetIPProperties(); + if (!ipProps.GatewayAddresses.Any()) + continue; + + if (ipProps.UnicastAddresses.Any(u => u.Address.Equals(addr))) { - var ipProps = nic.GetIPProperties(); - if (ipProps.GatewayAddresses.Any()) - { - if (ipProps.UnicastAddresses.Any(u => u.Address.Equals(addr))) - { - // if the preferred NIC has multiple addresses, boost all equally - // (justifies not bothering to differentiate... IOW YAGNI) - rankScore += 1000; - } - - // only considering the first NIC that is UP and has a gateway defined - break; - } + // if the preferred NIC has multiple addresses, boost all equally + // (justifies not bothering to differentiate... IOW YAGNI) + rankScore += 1000; } + + // only considering the first NIC that is UP and has a gateway defined + break; } return rankScore; } - private static IEnumerable TryGetCurrentNetworkInterfaces() - { - try - { - return NetworkInterface.GetAllNetworkInterfaces().Where(ni => ni.OperationalStatus == OperationalStatus.Up); - } - catch (NetworkInformationException) - { - return Enumerable.Empty(); - } - } - public SimpleTcpServer Start(int port, bool ignoreNicsWithOccupiedPorts = true) { - var ipSorted = GetIPAddresses(); - bool anyNicFailed = false; + var ipSorted = GetIpAddresses(); + var anyNicFailed = false; foreach (var ipAddr in ipSorted) { try @@ -167,18 +140,18 @@ public SimpleTcpServer Start(int port, bool ignoreNicsWithOccupiedPorts = true) if (!IsStarted) throw new InvalidOperationException("Port was already occupied for all network interfaces"); - if (anyNicFailed && !ignoreNicsWithOccupiedPorts) - { - Stop(); - throw new InvalidOperationException("Port was already occupied for one or more network interfaces."); - } + if (!anyNicFailed || ignoreNicsWithOccupiedPorts) + return this; - return this; + Stop(); + throw new InvalidOperationException("Port was already occupied for one or more network interfaces."); } public SimpleTcpServer Start(int port, AddressFamily addressFamilyFilter) { - var ipSorted = GetIPAddresses().Where(ip => ip.AddressFamily == addressFamilyFilter); + var ipSorted = GetIpAddresses() + .Where(ip => ip.AddressFamily == addressFamilyFilter); + foreach (var ipAddr in ipSorted) { try @@ -191,11 +164,9 @@ public SimpleTcpServer Start(int port, AddressFamily addressFamilyFilter) return this; } - public bool IsStarted { get { return _listeners.Any(l => l.Listener.Active); } } - - public SimpleTcpServer Start(IPAddress ipAddress, int port) + public SimpleTcpServer Start(IPAddress ipAddress, int port) { - Server.ServerListener listener = new Server.ServerListener(this, ipAddress, port); + var listener = new ServerListener(this, ipAddress, port); _listeners.Add(listener); return this; @@ -203,68 +174,67 @@ public SimpleTcpServer Start(IPAddress ipAddress, int port) public void Stop() { - _listeners.All(l => l.QueueStop = true); - while (_listeners.Any(l => l.Listener.Active)){ + _listeners.ForEach(l => l.QueueStop = true); + while (_listeners.Any(l => l.Listener.Active)) + { Thread.Sleep(100); - }; + } _listeners.Clear(); } - public int ConnectedClientsCount + internal void NotifyDelimiterMessageRx(ServerListener listener, TcpClient client, byte[] msg) { - get { - return _listeners.Sum(l => l.ConnectedClientsCount); - } - } + if (DelimiterDataReceived == null) + return; - internal void NotifyDelimiterMessageRx(Server.ServerListener listener, TcpClient client, byte[] msg) - { - if (DelimiterDataReceived != null) - { - Message m = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); - DelimiterDataReceived(this, m); - } + var message = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); + DelimiterDataReceived(this, message); } - internal void NotifyEndTransmissionRx(Server.ServerListener listener, TcpClient client, byte[] msg) + internal void NotifyEndTransmissionRx(ServerListener listener, TcpClient client, byte[] msg) { - if (DataReceived != null) - { - Message m = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); - DataReceived(this, m); - } + if (DataReceived == null) + return; + + var message = new Message(msg, client, StringEncoder, Delimiter, AutoTrimStrings); + DataReceived(this, message); } - internal void NotifyClientConnected(Server.ServerListener listener, TcpClient newClient) + internal void NotifyClientConnected(ServerListener listener, TcpClient newClient) + => ClientConnected?.Invoke(this, newClient); + + internal void NotifyClientDisconnected(ServerListener listener, TcpClient disconnectedClient) + => ClientDisconnected?.Invoke(this, disconnectedClient); + + private static IEnumerable TryGetCurrentNetworkInterfaces() { - if (ClientConnected != null) + try { - ClientConnected(this, newClient); + return NetworkInterface + .GetAllNetworkInterfaces() + .Where(ni => ni.OperationalStatus == OperationalStatus.Up); } - } - - internal void NotifyClientDisconnected(Server.ServerListener listener, TcpClient disconnectedClient) - { - if (ClientDisconnected != null) + catch (NetworkInformationException) { - ClientDisconnected(this, disconnectedClient); + return Enumerable.Empty(); } } - #region Debug logging + #region Debug logging + + private Stopwatch _debugInfoTime; - [System.Diagnostics.Conditional("DEBUG")] - void DebugInfo(string format, params object[] args) + [Conditional("DEBUG")] + private void DebugInfo(string format, params object[] args) { if (_debugInfoTime == null) { - _debugInfoTime = new System.Diagnostics.Stopwatch(); + _debugInfoTime = new Stopwatch(); _debugInfoTime.Start(); } - System.Diagnostics.Debug.WriteLine(_debugInfoTime.ElapsedMilliseconds + ": " + format, args); + Debug.WriteLine(_debugInfoTime.ElapsedMilliseconds + ": " + format, args); } - System.Diagnostics.Stopwatch _debugInfoTime; - #endregion Debug logging + #endregion Debug logging } }