Skip to content

Commit

Permalink
将SCS升级到.net standard 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
NeedJustWord committed Mar 8, 2019
1 parent fd048db commit cc516ef
Show file tree
Hide file tree
Showing 68 changed files with 5,555 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ ipch/
*.opensdf
*.sdf

# Visual Studio 2015 cache/options directory
.vs/

# Visual Studio profiler
*.psess
*.vsp
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ SCS - TCP Server/Client Communication and RMI Framework
You can download SCS binaries and source codes directly from here (Github).

If you're using Visual Studio, you can get from Nuget (https://www.nuget.org/packages/SCS).

### 更新日志

- 2019-03-08:参考[CoreProxy](https://github.com/ElderJames/CoreProxy)将SCS升级到.net standard 2.0。

197 changes: 197 additions & 0 deletions src/Scs.Core/Collections/ThreadSafeSortedList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
using System.Collections.Generic;
using System.Threading;

namespace Hik.Collections
{
/// <summary>
/// This class is used to store key-value based items in a thread safe manner.
/// It uses System.Collections.Generic.SortedList internally.
/// </summary>
/// <typeparam name="TK">Key type</typeparam>
/// <typeparam name="TV">Value type</typeparam>
public class ThreadSafeSortedList<TK, TV>
{
/// <summary>
/// Gets/adds/replaces an item by key.
/// </summary>
/// <param name="key">Key to get/set value</param>
/// <returns>Item associated with this key</returns>
public TV this[TK key]
{
get
{
_lock.EnterReadLock();
try
{
return _items.ContainsKey(key) ? _items[key] : default(TV);
}
finally
{
_lock.ExitReadLock();
}
}

set
{
_lock.EnterWriteLock();
try
{
_items[key] = value;
}
finally
{
_lock.ExitWriteLock();
}
}
}

/// <summary>
/// Gets count of items in the collection.
/// </summary>
public int Count
{
get
{
_lock.EnterReadLock();
try
{
return _items.Count;
}
finally
{
_lock.ExitReadLock();
}
}
}

/// <summary>
/// Internal collection to store items.
/// </summary>
protected readonly SortedList<TK, TV> _items;

/// <summary>
/// Used to synchronize access to _items list.
/// </summary>
protected readonly ReaderWriterLockSlim _lock;

/// <summary>
/// Creates a new ThreadSafeSortedList object.
/// </summary>
public ThreadSafeSortedList()
{
_items = new SortedList<TK, TV>();
_lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
}

/// <summary>
/// Checks if collection contains spesified key.
/// </summary>
/// <param name="key">Key to check</param>
/// <returns>True; if collection contains given key</returns>
public bool ContainsKey(TK key)
{
_lock.EnterReadLock();
try
{
return _items.ContainsKey(key);
}
finally
{
_lock.ExitReadLock();
}
}

/// <summary>
/// Checks if collection contains spesified item.
/// </summary>
/// <param name="item">Item to check</param>
/// <returns>True; if collection contains given item</returns>
public bool ContainsValue(TV item)
{
_lock.EnterReadLock();
try
{
return _items.ContainsValue(item);
}
finally
{
_lock.ExitReadLock();
}
}

/// <summary>
/// Removes an item from collection.
/// </summary>
/// <param name="key">Key of item to remove</param>
public bool Remove(TK key)
{
_lock.EnterWriteLock();
try
{
if (!_items.ContainsKey(key))
{
return false;
}

_items.Remove(key);
return true;
}
finally
{
_lock.ExitWriteLock();
}
}

/// <summary>
/// Gets all items in collection.
/// </summary>
/// <returns>Item list</returns>
public List<TV> GetAllItems()
{
_lock.EnterReadLock();
try
{
return new List<TV>(_items.Values);
}
finally
{
_lock.ExitReadLock();
}
}

/// <summary>
/// Removes all items from list.
/// </summary>
public void ClearAll()
{
_lock.EnterWriteLock();
try
{
_items.Clear();
}
finally
{
_lock.ExitWriteLock();
}
}

/// <summary>
/// Gets then removes all items in collection.
/// </summary>
/// <returns>Item list</returns>
public List<TV> GetAndClearAllItems()
{
_lock.EnterWriteLock();
try
{
var list = new List<TV>(_items.Values);
_items.Clear();
return list;
}
finally
{
_lock.ExitWriteLock();
}
}
}
}
110 changes: 110 additions & 0 deletions src/Scs.Core/Communication/Scs/Client/ClientReConnecter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using Hik.Communication.Scs.Communication;
using Hik.Threading;

namespace Hik.Communication.Scs.Client
{
/// <summary>
/// This class is used to automatically re-connect to server if disconnected.
/// It attempts to reconnect to server periodically until connection established.
/// </summary>
public class ClientReConnecter : IDisposable
{
/// <summary>
/// Reconnect check period.
/// Default: 20 seconds.
/// </summary>
public int ReConnectCheckPeriod
{
get { return _reconnectTimer.Period; }
set { _reconnectTimer.Period = value; }
}

/// <summary>
/// Reference to client object.
/// </summary>
private readonly IConnectableClient _client;

/// <summary>
/// Timer to attempt ro reconnect periodically.
/// </summary>
private readonly Timer _reconnectTimer;

/// <summary>
/// Indicates the dispose state of this object.
/// </summary>
private volatile bool _disposed;

/// <summary>
/// Creates a new ClientReConnecter object.
/// It is not needed to start ClientReConnecter since it automatically
/// starts when the client disconnected.
/// </summary>
/// <param name="client">Reference to client object</param>
/// <exception cref="ArgumentNullException">Throws ArgumentNullException if client is null.</exception>
public ClientReConnecter(IConnectableClient client)
{
if (client == null)
{
throw new ArgumentNullException("client");
}

_client = client;
_client.Disconnected += Client_Disconnected;
_reconnectTimer = new Timer(20000);
_reconnectTimer.Elapsed += ReconnectTimer_Elapsed;
_reconnectTimer.Start();
}

/// <summary>
/// Disposes this object.
/// Does nothing if already disposed.
/// </summary>
public void Dispose()
{
if (_disposed)
{
return;
}

_disposed = true;
_client.Disconnected -= Client_Disconnected;
_reconnectTimer.Stop();
}

/// <summary>
/// Handles Disconnected event of _client object.
/// </summary>
/// <param name="sender">Source of the event</param>
/// <param name="e">Event arguments</param>
private void Client_Disconnected(object sender, EventArgs e)
{
_reconnectTimer.Start();
}

/// <summary>
/// Hadles Elapsed event of _reconnectTimer.
/// </summary>
/// <param name="sender">Source of the event</param>
/// <param name="e">Event arguments</param>
private void ReconnectTimer_Elapsed(object sender, EventArgs e)
{
if (_disposed || _client.CommunicationState == CommunicationStates.Connected)
{
_reconnectTimer.Stop();
return;
}

try
{
_client.Connect();
_reconnectTimer.Stop();
}
catch (Exception exception)
{
//No need to catch since it will try to re-connect again
System.Diagnostics.Trace.Write($"ReconnectTimer_Elapsed: {exception}");
}
}
}
}
43 changes: 43 additions & 0 deletions src/Scs.Core/Communication/Scs/Client/IConnectableClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using Hik.Communication.Scs.Communication;

namespace Hik.Communication.Scs.Client
{
/// <summary>
/// Represents a client for SCS servers.
/// </summary>
public interface IConnectableClient : IDisposable
{
/// <summary>
/// This event is raised when client connected to server.
/// </summary>
event EventHandler Connected;

/// <summary>
/// This event is raised when client disconnected from server.
/// </summary>
event EventHandler Disconnected;

/// <summary>
/// Timeout for connecting to a server (as milliseconds).
/// Default value: 15 seconds (15000 ms).
/// </summary>
int ConnectTimeout { get; set; }

/// <summary>
/// Gets the current communication state.
/// </summary>
CommunicationStates CommunicationState { get; }

/// <summary>
/// Connects to server.
/// </summary>
void Connect();

/// <summary>
/// Disconnects from server.
/// Does nothing if already disconnected.
/// </summary>
void Disconnect();
}
}
13 changes: 13 additions & 0 deletions src/Scs.Core/Communication/Scs/Client/IScsClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Hik.Communication.Scs.Communication;
using Hik.Communication.Scs.Communication.Messengers;

namespace Hik.Communication.Scs.Client
{
/// <summary>
/// Represents a client to connect to server.
/// </summary>
public interface IScsClient : IMessenger, IConnectableClient
{
//Does not define any additional member
}
}
Loading

0 comments on commit cc516ef

Please sign in to comment.