For the project, I had to use real network connections in combination with SignalR.
For versions of Windows that do not support web ports, you can use the WebSocket4Net NuGet package and the following implementation of SignalR IClientTransport.
using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.SignalR.Client; using Microsoft.AspNet.SignalR.Client.Http; using Microsoft.AspNet.SignalR.Client.Infrastructure; using Microsoft.AspNet.SignalR.Client.Transports; using SuperSocket.ClientEngine; using WebSocket4Net; public sealed class WebSocket4NetTransport : ClientTransportBase { private IConnection _connection; private string _connectionData; private CancellationToken _disconnectToken; private CancellationTokenSource _webSocketTokenSource; private WebSocket _webSocket4Net; private int _disposed; public TimeSpan ReconnectDelay { get; set; } public WebSocket4NetTransport() : this(new DefaultHttpClient()) { } public WebSocket4NetTransport(IHttpClient client) : base(client, "webSockets") { _disconnectToken = CancellationToken.None; ReconnectDelay = TimeSpan.FromSeconds(2.0); } ~WebSocket4NetTransport() { Dispose(false); } protected override void OnStart(IConnection connection, string connectionData, CancellationToken disconnectToken) { _connection = connection; _connectionData = connectionData; _disconnectToken = disconnectToken; var connectUrl = UrlBuilder.BuildConnect(connection, Name, connectionData); try { PerformConnect(connectUrl); } catch(Exception ex) { TransportFailed(ex); } } protected override void OnStartFailed() { Dispose(); } public override Task Send(IConnection connection, string data, string connectionData) { if(_webSocket4Net.State == WebSocketState.Open) { _webSocket4Net.Send(data); } var ex = new InvalidOperationException("Socket closed"); connection.OnError(ex); throw ex; } public override void LostConnection(IConnection connection) { _connection.Trace(TraceLevels.Events, "WS: LostConnection"); if(_webSocketTokenSource == null) { return; } _webSocketTokenSource.Cancel(); } public override bool SupportsKeepAlive { get { return true; } } protected override void Dispose(bool disposing) { if(disposing) { if(Interlocked.Exchange(ref _disposed, 1) == 1) { base.Dispose(true); return; } if(_webSocketTokenSource != null) { _webSocketTokenSource.Cancel(); } if(_webSocket4Net != null) { DisposeWebSocket4Net(); } if(_webSocketTokenSource != null) { _webSocketTokenSource.Dispose(); } } base.Dispose(disposing); } private void DisposeWebSocket4Net() { _webSocket4Net.Error -= WebSocketOnError; _webSocket4Net.Opened -= WebSocketOnOpened; _webSocket4Net.Closed -= WebSocketOnClosed; _webSocket4Net.MessageReceived -= WebSocketOnMessageReceived; _webSocket4Net.Dispose(); _webSocket4Net = null; } private void PerformConnect(string url) { if(_webSocket4Net != null) { DisposeWebSocket4Net(); } _webSocketTokenSource = new CancellationTokenSource(); _webSocketTokenSource.Token.Register(WebSocketTokenSourceCanceled); CancellationTokenSource.CreateLinkedTokenSource(_webSocketTokenSource.Token, _disconnectToken);
To create a websocket client, use try-catch to determine which websocket implementation should be used.
using System; using System.Net.WebSockets; using Microsoft.AspNet.SignalR.Client.Transports; public static class WebSocketTransportFactory { public static IClientTransport Create() { IClientTransport clientTransport; try {
Start connecting to the SignalR hub.
var hubConnection = new HubConnection("https://url/to/the/hub"); var clientTransport = WebSocketTransportFactory.Create(); await hubConnection.Start(clientTransport);
Peter Mols
source share