Giter VIP home page Giter VIP logo

websocket-manager's Introduction

websocket-manager

Travis: Build Status

NuGet: NuGet

Simple middlware for real-time .NET Core

This is an Asp .Net Core middleware that provides real-time functionality to .NET Core applications.

To the core, it is a WebSocket middleware for Asp .Net Core with TypeScript / JavaScript client and .Net Core client that supports the client and the server invoking each others' methods.

Why wouldn't I use SignalR for this?

First of all, SignalR for Asp .Net Core is still in its very incipient stages. A preview is expected mid-2017, while a release near the end of 2017, so most probably it will be available for Asp .Net Core 2.0.

The preview and release information were taken from this talk by Damian Edwards and David Fowler, the guys in charge of Asp .Net Core.

What is this library's connection to SignalR?

This library is not an official release by Microsoft and in any way related to the original SignalR project, other by a lot of concepts inspired from it.

Because the release of SignalR for Asp .Net Core was delayed for so long, I decided to write a very basic, stripped down (compared to the original SignalR) that only supports WebSockets (is based on Microsoft.AspNetCore.WebSockets) with a TypeScript client.

A lot of features, both on the server side and the client side were written looking at SignalR (both old and new) code, so if you wrote SignalR in the past, the approach is very similar.

Get Started with websocket-manager

While it is still in development, you can see some examples of usage in the samples folder.

Contribute to websocket-manager

Contributions in any form are welcome! Submit issues with bugs and recommendations! Pull Requests are highly appreciated!

websocket-manager's People

Contributors

codeglitch0 avatar discostu105 avatar henry00is avatar jcyuan avatar mihai-burduselu avatar mikaelbr avatar miker1423 avatar milovidov983 avatar radu-matei avatar robschoenaker avatar ryanwersal avatar szumm avatar trydis avatar twodawg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websocket-manager's Issues

System.OutOfMemoryException

Can any one please help on this. I am getting OutOfMemoryException on array initialization. It happens in live only and not in local. It happens sometimes.

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at WebSocketManager.WebSocketManagerMiddleware.Receive(WebSocket socket, Action`2 handleMessage) in C:\Research\GIT\SP.Core\WebSocket-Manager\src\WebSocketManager\WebSocketManagerMiddleware.cs:line 102 at WebSocketManager.WebSocketManagerMiddleware.Invoke(HttpContext context) in C:\Research\GIT\SP.Core\WebSocket-Manager\src\WebSocketManager\WebSocketManagerMiddleware.cs:line 47 at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at
Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at NetCoreApp.Handler.CustomExceptionMiddleware.Invoke(HttpContext context) in

image

Inject dependency rather than using new

https://github.com/radu-matei/websocket-manager/blob/master/samples/ChatApplication/ChatHandler.cs#L11

In one sample, a dependency needed for the handler is newed-up rather than injected using dependency injection. This should not be handled by the user of the library, but rather by the library itself:

        public ChatHandler(WebSocketConnectionManager webSocketConnectionManager) : base(webSocketConnectionManager, new ControllerMethodInvocationStrategy())
        {
            ((ControllerMethodInvocationStrategy)MethodInvocationStrategy).Controller = this;
        }

cc @Henry00IS

Accessing from outside of a controller

Hi, I'm trying to access my websockets from outside in another service. Is there a way similar to how SignalR allow you to access Hubs via IHubContext?

Thanks!

Solid support and production-ready features

As I understand right now, SignalR will be supported for versions >= .NET Core 2.1 (and I assume .NET Standard 2.1), so I believe it is worth exploring and investigating issues that limit the use of this library in real workloads that will target .NET Core 1.x

Below is a set topics taken from the various issues and pull-requests here on GitHub, as well as additional features that might benefit users and should be updated according to work done in the repo (issues and pull-requests).

  • User Context and Identity

  • Distributed caching, Redis integration

  • Full Framework target

  • Dependency registration

  • Encoding

  • Logging

  • Groups

  • Performance

  • Serialization

  • Binary data transfer

  • Connection state / Reconnection

  • Samples

  • Tests

  • Investigate and merge existing pull-requests

  • Documentation and contributing guidelines

  • Automated release of NuGet

  • Update Travis CI

  • TypeScript / JavaScript client package release

  • Other clients (Go, Java, others)

Please feel free to add any other issues, feature requests or suggestions and let's try to create a schedule (and discussion) for rational versioning of the packages (right now the versioning does not make much sense)

I already sent contributor invitation to some of you, please let me know if anybody else is interested.

CC @skorunka @discostu105 @RobSchoenaker @miker1423 @CodeGlitch0 @mikaelbr @ryanwersal @trydis
(Please add other people in case I missed anyone)

I fail to run WebTerm

Hey,
Im very interested in WebTerm and I want to test it.
But I have a Problem to start it.
I cant run it with the arguments: "dotnet run".
It cant find the project file (But I have the file already in the same directory).
Can someone help me out. Thanks

Cannot inject dependencies in the sockethandler or use servicelocator to do so

Since the middleware is scoped differently in the service registration - it won't allow something to either be injected (obviously) or created inside that scope that is not scoped the same. For instance, I have a manager that I am using a special factory to instantiate - inside a method on the WebSocketHandler...

I tried scoping my factory in different ways - but because the handler (acting as the controller) is scoped differently then my manager... it won't allow it - in dotnetcore 2+

I don't see a nice way around this... because to do method injection on the invoke method would require me to either override and recode the invoke method or do something else wonky to get the classes that I need... any advice would be appreciated.

Thread safety

Consider the situation:

10 connected clients -> SendToAllAsync is invoked -> Last Socket Disconnects -> attempt to send message to the removed client. I'm almost sure that this will cause an exception. Could you comment on this, @radu-matei ?

Chat Rooms

Hi, one question... Can I manage a Chat Room with this library? Is possible? Thanks!

WebSocketManagerMiddleWare exception

When trying to use your package with latest .NET Core I am receiving this error

Message	"A suitable constructor for type 'WebSocketManager.WebSocketManagerMiddleware' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor."	string

on this line

 public static IApplicationBuilder MapWebSocketManager(this IApplicationBuilder app,
                                                              PathString path,
                                                              WebSocketHandler handler)
{
    return app.Map(path, (_app) => _app.UseMiddleware<WebSocketManagerMiddleware>(handler)); // here
}

Create unit tests for library

Tests need to be written for:

  • the middleware (xUnit)
  • .NET Client (xUnit)
  • TypeScript Client (karma?)

Then, they need to be integrated with continuous integration with Travis.

Suggestions: ControllerMethodInvocationStrategy with Async Tasks and ASP.NET Core 3.x Endpoints

Not really an issue but I wanted to submit back two possible enhancements that I made:

  1. Updated ControllerMethodInvocationStrategy to handle Tasks (async functions) in addition to normal functions:
    -Replaced-
    return await Task.Run(() => method.Invoke(Controller, args.ToArray()));
    -with-
                var result = await Task.Run(() => method.Invoke(Controller, args.ToArray()));
                if (result == null) return null;
                var resultType = result.GetType();
                if (resultType == typeof(Task)) return null;
                if (resultType.IsGenericType && resultType.GetGenericTypeDefinition() == typeof(Task<>))
                    return resultType.GetProperty("Result")?.GetValue(result);
                return result;
  1. Added a set of extension to allow WebSockManager to be used with Endpoints (ASP.NET Core 3.x):
public static class EndpointRouteBuilderExtensions
    {
        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="path">Path</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, string path)
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            return builder.MapWebSocketManager(path, builder.ServiceProvider.GetRequiredService<THandler>());
        }

        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="path">Path</param>
        /// <param name="handlerFunc">Function that creates the Web Socket Handler</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, string path, Func<IServiceProvider,THandler> handlerFunc)
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            return builder.MapWebSocketManager(path, handlerFunc(builder.ServiceProvider));
        }

        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="path">Path</param>
        /// <param name="handler">Web Socket Handler</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, string path, THandler handler) 
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path));
            if (handler == null) throw new ArgumentNullException(nameof(handler));
            return builder.Map(path, builder
                .CreateApplicationBuilder()
                .UseWebSockets()
                .UseMiddleware<WebSocketManagerMiddleware>(handler)
                .Build()
            );
        }

        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="routePattern">Route Pattern</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, RoutePattern routePattern)
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            return builder.MapWebSocketManager(routePattern, builder.ServiceProvider.GetRequiredService<THandler>());
        }

        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="routePattern">Route Pattern</param>
        /// <param name="handlerFunc">Function that creates the Web Socket Handler</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, RoutePattern routePattern, Func<IServiceProvider, THandler> handlerFunc)
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            return builder.MapWebSocketManager(routePattern, handlerFunc(builder.ServiceProvider));
        }

        /// <summary>
        /// Add a WebSocketManager Handler that listens to a specific path.
        /// </summary>
        /// <typeparam name="THandler">Handler Type</typeparam>
        /// <param name="builder">Endpoint Builder</param>
        /// <param name="routePattern">Route Pattern</param>
        /// <param name="handler">Web Socket Handler</param>
        /// <returns>Endpoint Convention Builder</returns>
        public static IEndpointConventionBuilder MapWebSocketManager<THandler>(this IEndpointRouteBuilder builder, RoutePattern routePattern, THandler handler)
            where THandler : WebSocketHandler
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            if (routePattern == null) throw new ArgumentNullException(nameof(routePattern));
            if (handler == null) throw new ArgumentNullException(nameof(handler));
            return builder.Map(routePattern, builder
                .CreateApplicationBuilder()
                .UseWebSockets()
                .UseMiddleware<WebSocketManagerMiddleware>(handler)
                .Build()
            );
        }
    }

Question about scaling this

So I realize this is somewhat new-ish project, are there any mechanisms to facilitate scaling (say if site took off and I wanted to run this stuff across 10 web servers?)

NuGet update

Hey there!
Your middleware has been really beneficial for me and a friend. My friend is also blogging and will be crediting you as he's used your code - however, he saw you had a NuGet package but it's not been updated recently.
Are there plans to update it soon?
Layla

The remote party closed the WebSocket connection without completing the close handshake.

Then client is disconnected (net error or else), server down with error;

System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake.

I use NuGet package, hoe to process this errors and drop sockets from disconnected clients withoun server down?

Sample's Documentation

Very good work, any explantion how examples working would be good. Not sure how to run the example's.

Satya

Build string to send in socket to server

I try to send message in websocket from other soft, wich must send only string.

I intercept string in demo chat and have this:

{
"$type": "WebSocketManager.Common.Message",
"messageType": 1,
"data": {
"$type": "WebSocketManager.Common.InvocationDescriptor",
"methodName": "SendMessage",
"arguments": {
"$type": "System.Object[]",
"$values": [
{
"$type": "System.String",
"$value": "test"
}
]
},
"identifier": {
"$type": "System.Guid",
"$value": "00000000-0000-0000-0000-000000000000"
}
}
}

When i send this string to websocket, i get error:

Newtonsoft.Json.JsonSerializationException: "Type specified in JSON 'WebSocketManager.Common.InvocationDescriptor, WebSocketManager.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'. Path 'data.$type', line 5, position 59."

Please, how the string to send to server must be?

WebSocketHandler and WebSocketConnectionManager lifetime

Hi,

Any reason to set the WebSocketHandler service as a Singleton and WebSocketConnectionManager service as transient?

From my point of view WebSocketConnectionManager should be a Singleton and WebSocketHandler a transient or scoped service as the entry point for the websocket is the handler, we don't have to keep it as a singleton but allow other scoped DI to be used inside the handler (like for EF #68 - #72)

To be able to keep mapped route to specific handler, I tried to give to the middleware the handler type (like app.MapWebSocketManager<ConnectionHandler>("/connection");) and calling var webSocketHandler = (WebSocketHandler)serviceProvider.GetService(_handlerType); directly in the middleware Invoke function.
This is working fine but I don't know if it's the best way to do runtime dependency injection setup.

Regards

How to call server in c# client

I tried this but no success.

InvocationDescriptor invocation = new InvocationDescriptor();
invocation.Identifier = Guid.Parse(_clientId);
invocation.MethodName = "CallServer";

        await _connection.SendAsync(invocation);

on the server:
public async Task CallServer()
{
}

How to hosting Chat application in IIS

Hello,

I would like to host my web page which uses your WebSocketmanager Api in IIS on my Windows 10 machiene.
Could you please show this in a tutorial.

Add protobuf support

Right now, this library only supports sending messages as JSON - it would be a great addition if we supported protobuf.

json format to sent message

May I know what is the json format to sent message? I want to sendmessage from desktop application. The example only has javascript library.

WebsocketManager dictionary in a distributed cache?

Hi,
I have implemented this approach on my web application but I want to extend it by using a distributed cache (redis).
Is there a way to save the dictionary in redis just like I could do with session variables?

I am using .net core 2.

WebSocketManagerExtensions: registration of dependencies

Should be the WebSocketConnectionManager registered as singleton instead of user defined WebSocketHandlers?

Imagine the situation where you want to resolve some resources in your WebSocketHandler which are dependent on the request context = so they differ per request.

I think the better implementation is:

	public static IServiceCollection AddWebSocketManager(this IServiceCollection services)
	{
		services.AddSingleton<WebSocketConnectionManager>();

		foreach (var type in Assembly.GetEntryAssembly().ExportedTypes)
		{
			if (type.GetTypeInfo().BaseType == typeof(WebSocketHandler))
			{
				services.AddScoped(type);
			}
		}

		return services;
	}

Handle dead client's connections ?

Hi,
I suppose, Web manager could send periodically messages to client, to verify its connection.
Client could send a REST request only for verification (maybe to include also in its request a timestamp, provided by the manager's initiated message). Then the controller to send message to web manager to update a "keep alive" list with clients responses. Web manager periodically could clean the connections without "keep alive" responses.
Unfortunately, I don't have time, for a while, to help your excellent effort.

WebSocketManagerMiddleware class throws Websocket Exception when the socket is not properly closed

I've been struggling to find this problem for the past 24 hours.

In the WebSocketManagerMiddleware class, the awaitable Receive Task will throw an unhandled Websocket Exception that will break the application in the case of a socket not being properly closed. The ExceptionHandlerMiddleware was unable to catch it as well, not sure why.

The exact message is something like "The remote party closed the WebSocket connection without completing the close handshake."

This can probably be replicated using the mvc sample, then using a cellphone to connect to the websocket and then switching back to another process so the browser will be in background.

json error in mvc sample

from debug console:

Sending through HTTP to a controller:test
VM117:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse ()
at WebSocket.socket.onmessage (WebSocketManager.js:106)
socket.onmessage @ WebSocketManager.js:106

Return the same id to client on reload

Is it possible to get the same id to the client even when the user reloads the web page? I would like to send notifications even though the user has navigated away from the initial page.

NuGet package upgrade

First of all, thank you for all the great work and time you spent developing the WebSocketManager.
I was wondering if you will consider publishing a new version of the NuGet package, there's a lot of good features that are not in the current version of the NuGet Package and it will be nice to have them there.
Thank you.

Socket still live after client disconnect

Hi,

When client lost connection because crash or modem shutdown, server continue with socket in memory and OnDisconnected event in websockethandler is never executed.

In statup have configuration to keepaliveinterval = 60 seconds, but after this time, socket continue in memory and OnDisconnected event is never executed.

Anyhere have solution to detect when socket client crash to remove socket from memory or make other actions ?

Thank you,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.