@@ -4,27 +4,27 @@
using System . Threading ;
using System . Threading . Tasks ;
namespace Coe . WebSocketWrapper
namespace System . Net . Sockets
{
public class WebSocketWrapper
public class WebSocketWrapper : IDisposable
{
private const int ReceiveChunkSize = 1024 ;
private const int SendChunkSize = 1024 ;
private readonly ClientWebSocket _ws ;
public readonly ClientWebSocket Client ;
private readonly Uri _uri ;
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource ( ) ;
private readonly CancellationToken _cancellationToken ;
private Action < WebSocketWrapper > _onConnected ;
private Action < string , WebSocketWrapper > _onMessage ;
private Action < WebSocketWrapper > _onDisconnected ;
public event Action < WebSocketWrapper > OnConnected ;
public event Action < WebSocketWrapper , string > OnMessage ;
public event Action < WebSocketWrapper > OnDisconnected ;
protected WebSocketWrapper ( string uri )
protected WebSocketWrapper ( Uri uri )
{
_ws = new ClientWebSocket ( ) ;
_ws . Options . KeepAliveInterval = TimeSpan . FromSeconds ( 20 ) ;
_uri = new Uri ( uri ) ;
Client = new ClientWebSocket ( ) ;
Client . Options . KeepAliveInterval = TimeSpan . FromSeconds ( 20 ) ;
_uri = uri ;
_cancellationToken = _cancellationTokenSource . Token ;
}
@@ -33,7 +33,7 @@ protected WebSocketWrapper(string uri)
/// </summary>
/// <param name="uri">The URI of the WebSocket server.</param>
/// <returns></returns>
public static WebSocketWrapper Create ( string uri )
public static WebSocketWrapper Create ( Uri uri )
{
return new WebSocketWrapper ( uri ) ;
}
@@ -49,38 +49,13 @@ public WebSocketWrapper Connect()
}
/// <summary>
/// Set the Action to call when the connection has been established.
/// </summary>
/// <param name="onConnect">The Action to call.</param>
/// <returns></returns>
public WebSocketWrapper OnConnect ( Action < WebSocketWrapper > onConnect )
{
_onConnected = onConnect ;
return this ;
}
/// <summary>
/// Set the Action to call when the connection has been terminated.
/// </summary>
/// <param name="onDisconnect">The Action to call</param>
/// <returns></returns>
public WebSocketWrapper OnDisconnect ( Action < WebSocketWrapper > onDisconnect )
{
_onDisconnected = onDisconnect ;
return this ;
}
/// <summary>
/// Set the Action to call when a messages has been received.
/// Connects to the WebSocket server.
/// </summary>
/// <param name="onMessage">The Action to call.</param>
/// <returns></returns>
public WebSocketWrapper OnMessage ( Action < string , WebSocketWrapper > onMessage )
public void Disconnect ( )
{
_onMessage = onMessage ;
return this ;
Client . CloseAsync ( WebSocketCloseStatus . NormalClosure , "Normal" , CancellationToken . None ) ;
}
/// <summary>
/// Send a message to the WebSocket server.
/// </summary>
@@ -92,15 +67,15 @@ public void SendMessage(string message)
private async void SendMessageAsync ( string message )
{
if ( _ws . State != WebSocketState . Open )
if ( Client . State != WebSocketState . Open )
{
throw new Exception ( "Connection is not open." ) ;
}
var messageBuffer = Encoding . UTF8 . GetBytes ( message ) ;
var messagesCount = ( int ) Math . Ceiling ( ( double ) messageBuffer . Length / SendChunkSize ) ;
for ( var i = 0 ; i < messagesCount ; i ++ )
for ( var i = 0 ; i < messagesCount ; i ++ )
{
var offset = ( SendChunkSize * i ) ;
var count = SendChunkSize ;
@@ -111,13 +86,13 @@ private async void SendMessageAsync(string message)
count = messageBuffer . Length - offset ;
}
await _ws . SendAsync ( new ArraySegment < byte > ( messageBuffer , offset , count ) , WebSocketMessageType . Text , lastMessage , _cancellationToken ) ;
await Client . SendAsync ( new ArraySegment < byte > ( messageBuffer , offset , count ) , WebSocketMessageType . Text , lastMessage , _cancellationToken ) ;
}
}
private async void ConnectAsync ( )
{
await _ws . ConnectAsync ( _uri , _cancellationToken ) ;
await Client . ConnectAsync ( _uri , _cancellationToken ) ;
CallOnConnected ( ) ;
StartListen ( ) ;
}
@@ -128,20 +103,20 @@ private async void StartListen()
try
{
while ( _ws . State == WebSocketState . Open )
while ( Client . State == WebSocketState . Open )
{
var stringResult = new StringBuilder ( ) ;
WebSocketReceiveResult result ;
do
{
result = await _ws . ReceiveAsync ( new ArraySegment < byte > ( buffer ) , _cancellationToken ) ;
result = await Client . ReceiveAsync ( new ArraySegment < byte > ( buffer ) , _cancellationToken ) ;
if ( result . MessageType == WebSocketMessageType . Close )
{
await
_ws . CloseAsync ( WebSocketCloseStatus . NormalClosure , string . Empty , CancellationToken . None ) ;
Client . CloseAsync ( WebSocketCloseStatus . NormalClosure , string . Empty , CancellationToken . None ) ;
CallOnDisconnected ( ) ;
}
else
@@ -162,31 +137,39 @@ private async void StartListen()
}
finally
{
_ws . Dispose ( ) ;
Client . Dispose ( ) ;
}
}
private void CallOnMessage ( StringBuilder stringResult )
{
if ( _onMessage != null )
RunInTask ( ( ) => _onMessage ( stringResult . ToString ( ) , this ) ) ;
if ( OnMessage != null )
RunInTask ( ( ) => OnMessage ( this , stringResult . ToString ( ) ) ) ;
}
private void CallOnDisconnected ( )
{
if ( _onDisconnected != null )
RunInTask ( ( ) => _onDisconnected ( this ) ) ;
if ( OnDisconnected != null )
RunInTask ( ( ) => OnDisconnected ( this ) ) ;
}
private void CallOnConnected ( )
{
if ( _onConnected != null )
RunInTask ( ( ) => _onConnected ( this ) ) ;
if ( OnConnected != null )
RunInTask ( ( ) => OnConnected ( this ) ) ;
}
private static void RunInTask ( Action action )
{
Task . Factory . StartNew ( action ) ;
}
public void Dispose ( )
{
if ( Client != null )
{
Client . Dispose ( ) ;
}
}
}
}
}