Giter Site home page Giter Site logo

aspnet / websockets Goto Github PK

View Code? Open in Web Editor NEW
357.0 74.0 113.0 786 KB

[Archived] Implementation of the WebSocket protocol, along with client and server integration components.

License: Apache License 2.0

Shell 7.77% C# 84.28% Batchfile 0.40% PowerShell 7.55%
aspnet-product

websockets's Introduction

WebSockets [Archived]

This GitHub project has been archived. Ongoing development on this project can be found in https://github.com/aspnet/AspNetCore.

Contains a managed implementation of the WebSocket protocol, along with server integration components.

This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the AspNetCore repo.

System Requirements

This repo has a few special system requirements/prerequisites.

  1. Windows IIS Express tests require IIS Express 10 and Windows 8 for WebSockets support
  2. HttpListener/ASP.NET 4.6 samples require at least Windows 8
  3. Autobahn Test Suite requires special installation see the README.md in test/AutobahnTestApp

websockets's People

Contributors

ajaybhargavb avatar analogrelay avatar aspnetci avatar avanderhoorn avatar brennanconroy avatar bricelam avatar chengtian avatar dasmulli avatar davidfowl avatar dougbu avatar eilon avatar forki avatar halter73 avatar haok avatar hishamco avatar jkotalik avatar juntaoluo avatar kichalla avatar kirthik avatar mikeharder avatar natemcmaster avatar ntaylormullen avatar pakrym avatar pranavkm avatar ryanbrandenburg avatar tratcher avatar troydai 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  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

websockets's Issues

Validate reserved bits

The WebSocket protocol defines several reserved bits in the various frames and says that the connection should be failed if any of those bits are ever set. See section 3 of the autobahn tests.

WebSocket.ReceiveAsync throws exceptions

I am porting over my networking library to dotnetcore. My websocket transport is nearly identical, except I am using Kestrel instead of an HTTP Listener. When I call ReceiveAsync, I get request aborted exceptions. If I add an arbitrary yield, the error changes to a NRE.

        public Task<WebSocketReceiveResult> ReadAsync()
        {
            buffer = new ArraySegment<byte>(BufferFactory.Rent(BufferFactory.MAXIMUM_SIZE));

            //THROWS HERE
            return webSocket.ReceiveAsync(buffer, CancellationToken.None);
        }


        public async void Update()
        {
            try
            {
                 // await Task.Yeild; // arbitrary yield for exception 2.

                //THROWS HERE
                var received = await ReadAsync();

                while (webSocket != null && received.MessageType != WebSocketMessageType.Close)
                {
                    if (received.MessageType == WebSocketMessageType.Binary)
                    {
                        OnDataReceive(this, buffer.Array);
                        received = await ReadAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                OnException(this, ex);
            }
            finally
            {
                Close();
            }
        }

Without the yield I get this exception

The request was aborted

When I add the yield my exception changes to this

Cannot access a disposed object.\r\nObject name: 'FrameRequestStream'.

Stack Trace

" at Microsoft.AspNetCore.Server.Kestrel.Http.SocketInput.GetResult()\r\n at Microsoft.AspNetCore.Server.Kestrel.Http.SocketInputExtensions.d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.d__38.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.d__37.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.d__36.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at Signaling.Server.Ws.WSConnection.d__35.MoveNext() in G:\Drive\Avarice\Foundation\Foundation.Signaling\Signaling\Signaling.Server.Ws\WSConnection.cs:line 67"

ClientSide I am using Websocket4Net and WebsocketSharp

Implement utf-8 validation

The WebSocket protocol requires that utf-8 messages be strictly validated on both ends. The managed native implementation does this, but the managed one does not. This accounts for the bulk of the failures in the autobahn tests.

Note that this deep validation may be expensive enough to consider making it optional.

Support for Ping-pong with callback

Hi,

It would be nice if the package would support the server initiating a ping to the client to check if it's still connected or not.
Currently (and please correct me if I'm wrong) the only to make sure the server doesn't accumulates already dead web sockets is the do ping-pong with messages instead of ping-pong frames.

Thanks,
Doron

Unexpected end of stream - Should be close?

fail: AgeOfAscent.Space.SpaceWebSocketsMiddleware[1]
      PlayerWebsocket error System.AggregateException: One or more errors occurred. ---> System.IO.IOException: Unexpected end of stream
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<EnsureDataAvailableOrReadAsync>d__38.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<ReadNextFrameAsync>d__37.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<ReceiveAsync>d__36.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<CompleteReceiveTaskAsync>d__57.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 311
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<ReceiveProcessAsync>d__54.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 276
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<ReceiveAsync>d__53.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 266
         --- End of inner exception stack trace ---
      ---> (Inner Exception #0) System.IO.IOException: Unexpected end of stream
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<EnsureDataAvailableOrReadAsync>d__38.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<ReadNextFrameAsync>d__37.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.WebSockets.Protocol.CommonWebSocket.<ReceiveAsync>d__36.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<CompleteReceiveTaskAsync>d__57.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 311
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<ReceiveProcessAsync>d__54.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 276
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at AgeOfAscent.Web.Network.PlayerWebsocket.<ReceiveAsync>d__53.MoveNext() in I:\IllyriadGames.AgeOfAscent\src\AgeOfAscent.Space\Network\PlayerWebsocket.cs:line 266<---

subprotocol is not returned in WebSocket Upgrade / Accept Response

the following JS:
var exampleSocket = new WebSocket("ws://" + window.location.host, "test");
when accepted by:
WebSocket webSocket = await httpContext.WebSockets.AcceptWebSocketAsync("test");
does not include the header value:
Sec-WebSocket-Protocol:test

even though it should per spec.

Websockets.Client does not support DNXCore

I get this error when trying to add Microsoft.AspNet.WebSockets.Client as a dependency of a DNXCore application:

The dependency Microsoft.AspNet.Websockets.Client 1.0.0-rc1-final in project "..." does not support framework DNXCore,Version=v5.0

A quick glance at the project.json for the Protocol and Server projects shows that they correctly target DNXCore, but Client does not. Any way we can get that changed?

Drain data on close

Clients should wait for the server to close the connection. Read from the socket until zero is returned.

Validate close frames

Autobahn tests
7.3.2 - Send a close frame with payload length 1 - Clean close with protocol error or drop TCP.
7.3.6 - Send a close frame with close code and close reason which is too long (124) - total frame payload 126 octets - Clean close with protocol error code or dropped TCP connection.

keep-alive semantics

Hi - Can you please clarify how keep-alives are supposed to work?

I would like to ensure that a client is currently connected, eg: by sending a ping every second, and expecting a pong (say, within 3 seconds).

However, the pong response is handled under the covers by the websocket library. There doesn't seem to be a way for my app to know when, or even if, the client ever responds with a pong.

Note that simply setting a ReadTimeout on the underlying socket stream would solve this problem. I don't see how this is possible with a websocket returned in an aspnet core 1 app via

var webSocket = await context.WebSockets.AcceptWebSocketAsync();

Am I forced to create my own keep-alive messages? If so, what is the point of websocket ping/pong at all?

thanks,
--craig

Validate close status codes

Autobahn tests section 7.9 - Send invalid close status codes. Clean close with protocol error code or drop TCP.

NuGet package versions for client and server are out of sync

The most recent version of Microsoft.AspNetCore.WebSockets.Server that is available as a NuGet package is 0.1.0-rc2-final, and its dependencies that are a part of ASP.NET Core all seem to be 1.0.0-rc2-final:

https://www.nuget.org/packages/Microsoft.AspNetCore.WebSockets.Server/0.1.0-rc2-final

On the other hand, for Microsoft.AspNetCore.WebSockets.Client on NuGet, the most recent package is 1.0.0-rc1-final, and it depends on different versions of other packages (in particular, Microsoft.AspNet.WebSockets.Protocol).

Is that by design and supposed to "just work" despite mismatched versions? Or is there an updated package for the client that matches the server (in terms of versions of packages it depends on)?

Native/Managed clarification

Could you please add more information to readme file about what is the difference between native and managed implementations and in which cases the managed one should be preferable.

Automate Autobahn server test suite

Add automation to run the Autobahn Test Suite against the WebSocket middleware

This will involve launching Python so we'll need some scripting to detect Python and fail as appropriate, or install it or something.

  • Check in the necessary code to run it on build
  • Update CI infrastructure as needed to include necessary support files (Autobahn Runner, etc.)
  • Include test apps for HttpListener and ASP.NET 4
  • Enable Autobahn runs on each build.
  • Provide simple infrastructure to run individual test cases against a server

Fix flaky test: SendLongData

DFowler: One of the tests fails randomly for me:

Microsoft.Net.WebSockets.Test.WebSocketClientTests.SendLongData_Success [FAIL]
Assert.True() Failure
Stack Trace:
Seems like a race condition since adding a random sleep makes it work more consistently.

Validate ping payload limits

Autobahn test case 2.5 - Send ping with binary payload of 126 octets. Connection should be failed immediately (1002/Protocol Error), since control frames are only allowed to have payload up to and including 125 octets.

Add WebSocket functional tests

From @Tratcher on October 20, 2015 1:0

From @Sharpiro on October 19, 2015 17:29

IHttpUpgradeFeature "IsUpgradableRequest" is never true in IIS Express profile, but works when running from kestrel via default "web" profile. Likely an issue with: "Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8"

Repro:

Create an empty web application from the asp.net 5 templates. Add the following lines of code inside app.Run inside Startup.cs:

var temp = context.Features.Get<IHttpUpgradeFeature>().IsUpgradableRequest;
var upgradeFeature = context.Features.Get<IHttpUpgradeFeature>();

Send the following line of code via a web browser:

var socket = new WebSocket("ws://localhost:---your port here---");

I am able to achieve a "true" value from "temp" when running from kestrel "web" profile only. The "temp" value is always false when running form IIS Express.

Copied from original issue: dotnet/aspnetcore#1005

Copied from original issue: aspnet/IISIntegration#19

Maximum of 8 connections

I am migrating my server to dotnetcore. Before I was using Fleck and Netgains as my websocket transport and was able to sustain many clients. Now, I am using AspNet.Websockets, and I cant get past 8 connections. I think I am missing something very simple in my implementation.

Here is my server code.

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {

        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseWebSockets();

            app.Use(Middleware);
        }

        public async Task Middleware(HttpContext http, Func<Task> func)
        {
            try
            {
                // is this http request a WS request ?
                if (!http.WebSockets.IsWebSocketRequest)
                {
                    // Nothing to do here, pass downstream.  
                    await func();
                }

                //Accept handshake
                var webSocket = await http.WebSockets.AcceptWebSocketAsync();

                // sanity for failed handshake
                if (webSocket != null && webSocket.State == WebSocketState.Open)
                {
                    await Echo(webSocket);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }


        private async Task Echo(WebSocket webSocket)
        {
            byte[] buffer;

            WebSocketReceiveResult result = null;

            buffer = new byte[1024 * 2];
            while (result == null || !result.CloseStatus.HasValue)
            {
                //buffer = ArrayPool<byte>.Shared.Rent(1024*2);
                var receiver = new ArraySegment<byte>(buffer);
                result = await webSocket.ReceiveAsync(receiver, CancellationToken.None);

                var sender = new ArraySegment<byte>(buffer, 0, result.Count);
                await webSocket.SendAsync(sender, WebSocketMessageType.Binary, true, CancellationToken.None);
               // ArrayPool<byte>.Shared.Return(buffer);
            }

            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        }
    }

Here is my client code

public class TestClient
    {
        public bool Connected;
        public int Messages;
        public int Errors;
        public bool DoEcho;
        public double Latency;

        public double LatencyCounter;
        public Stopwatch Watch = new Stopwatch();

        public void Run(string path, int pageSize, Func<byte[]> onSend, Func<byte[], bool> onReceive  )
        {
            Task.Run(() =>
            {
                var client = new WebSocket(path);

                Action doSend = () =>
                {
                    Watch.Start();
                    byte[] message = onSend();
                    client.Send(message, 0, message.Length);
                };

                client.Opened += (sender, args) =>
                {
                    Connected = true;

                    while (!DoEcho)
                    {
                        Task.Yield();
                    }

                    doSend();
                };
                client.Closed += (sender, args) =>
                {
                    Connected = false;
                    throw new Exception("Failed Test");
                };
                client.DataReceived += (sender, args) =>
                {
                    if (!onReceive(args.Data))
                    {
                        throw new Exception("Failed Test");
                    }

                    Messages++;
                    LatencyCounter += Watch.ElapsedMilliseconds;
                    Latency = LatencyCounter/Messages;

                    doSend();
                };
                client.Error += (sender, args) =>
                {
                    throw new Exception("Failed Test");
                };

                client.Open();
            });
        }
    }

Bearer token header

If I need to add a bearer token before handshake so that I accept only the connections that have a valid token, what is the correct way to do so?

After this line, should I just add this:

WebSocketClient client = new WebSocketClient();
client.ConfigureRequest = (req) =>
{
    req.Headers.Add("Bearer ", _tokenValue);
};

That is similar to what I used to do in SignalR. Is this the correct way to make identity middleware work and then use it before accepting a WS request? Thanks!

Connection always aborts with CLOSE_ABNORMAL(1006) with WebKit-Browsers

Title

Connection always aborts with CLOSE_ABNORMAL(1006) with WebKit-Browsers.

Functional impact

The client can not receive the sent WebSocketCloseStatus-Codes since the connection always seems to be aborted, whereupon the browser returns the StatusCode CLOSE_ABNORMAL(1006).

Minimal repro steps

  • Scaffold a new rc1-final Web-API project (I can not use rc2 since my linux distro is not supported yet).
  • Add the missing dependency to the project.json:
"Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-final"
  • Replace the code in Startup.cs with the following (mostly copied from TestServer):
using System;
using System.Net.WebSockets;
using System.Threading;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.Logging;

namespace wsTest
{
    public class Startup
    {

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();  
            loggerFactory.AddDebug();

            app.UseWebSockets();
            app.Use(async (context, next) =>
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    var client = await context.WebSockets.AcceptWebSocketAsync();

                    byte[] buffer = new byte[1024];
                    WebSocketReceiveResult received = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                    while (received.MessageType != WebSocketMessageType.Close)
                    {
                        await client.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count), received.MessageType, received.EndOfMessage, CancellationToken.None);
                        received = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                    }
                    await client.CloseAsync(received.CloseStatus.Value, received.CloseStatusDescription, CancellationToken.None);

                }
            });
        }

        public static void Main(string[] args) => Microsoft.AspNet.Hosting.WebApplication.Run<Startup>(args);
    }
}
  • Run the server
  • Open a Webkit-Based browser's Developer Tools window, go to the console and paste the following:
var handler = function(){console.log(arguments);};
var test = new WebSocket('ws://localhost:5000');
test.onclose = handler;
test.onopen = handler;
test.onerror = handler;
test.onmessage = handler;

now try:

test.close();

Expected result

The connection should be normally closed with the code CLOSE_NORMAL(1000).

Actual result

The connection is aborted, and the CloseEvent (which is logged to the Browser-Console in the example) shows the code: CLOSE_ABNORMAL(1006).

Misc Info

  • Operating System: Linux OpenSUSE Tumbleweed
  • Tested browsers: Opera-37.0.2178.32, Chromium-50.0.2661.102, Firefox-46.0.
  • Works fine with tested Firefox.

Did I do something wrong in the code?

SendAsync, ReceiveAsync semantics inconsistency between different implementations

There are some incosistencies in implementations of web sockets: (Helios, Reference:AspNetWebSocket, .NET Core:CommonWebSocket)

ReceiveAsync is not that bad:

  1. HeliosWebSocket throws exceptions in case of two simultaneous ReceiveAsync are in place - this is consistent with reference documentation: http://referencesource.microsoft.com/#System.Web/WebSockets/AspNetWebSocket.cs ThrowIfReceiveUnavailable - checks for Busy state which is set during every ReceiveAsync
    From my experiment HeliosWebSocket behaves the same
    CommonWebSocket - does behave differently BUT! it has a proper code comment: // TODO: InvalidOperationException if any receives are currently in progress.

So I can safely assume that reference semantics are the expected ones.
2. In case of SendAsync it's a bit worse:
It's well documented in reference implementation:
// - We'll detect multiple calls to SendAsync (e.g. a second call takes place while the first
// call isn't yet complete) and throw an appropriate exception. CloseOutputAsync is
// an equivalent of SendAsync for this purpose.
HeliosWebSockets acts accordingly (from my experiments).
CommonWebSocket uses asynchronous _writeLock during entire operations - so it safely allows multiple subsequent SendAsync and there is not intention in comments to unify semantics.

What are the intended semantics for ASP.NET 5? Single SendAsync at a time and single ReceiveAsync at a time? And it is a bug? Or SingleReceiveAsync and multiple SendAsyncs at a time and HelliosWebSockets are going to be updated?

[Announcement] WebSockets disabled in WebListener for v1

WebSockets are not on the roadmap for ASP.NET 5 v1. This has the following implications:
A) WebSockets have been disabled in Microsoft.AspNet.Server.WebListener. Opaque upgrades still work so Microsoft.AspNet.WebSockets.Server middleware can still be used to add the functionality.
B) Microsoft.Net.WebSockets has been renamed to Microsoft.Net.WebSockets.Server and refactored to be an optional package that can be added on top of Microsoft.Net.Http.Server. This is for developers that are using WebListener independent of Asp.Net.
C) Microsoft.Net.WebSockets.Server and Microsoft.AspNet.WebSockets.* will not be shipped to nuget.org with the final 1.0 release. Pre-releases will continue to be available on myget.org.

We will revisit WebSockets after v1.

Autobahn Failure: UTF-8 handling, WebListener with Managed Web Sockets

Tracking a suppressed failure in the Autobahn suite for review and fixing later.

Cases 6.1.2 and 6.1.3 fail on WebListener with the managed web sockets implementation. These appear to be simple tests that send a fragmented UTF-8 message (where each fragment is itself valid UTF-8) and expect the result to be echoed back. However, the connection is being terminated abruptly by the server.

WebSocketHandler.SendAsync can throw

I am unsure if you will consider that a bug (or design flaw) or not.

Looking at the source, and given that using websockets is very async by nature (disconnection can happen any time), I assumed that calling SendAsync was safe and need not a try..catch around it.

But in fact, it's not. It checks WebSocket.Status, which throws when WebSocket was disposed (at least the HeliosWebSocket does -- I know you dropped Helios, I just haven't tested another implementation yet). So if the socket is closed (e.g. client disconnects) at the bad time SendAsync will throw.

Solutions:

  • wrap all your calls to SendAsync in try..catch but that doesn't quite feel right.
  • in your derived SebSocketHandler add some kind of synchronization between OnClose and SendAsync (and probably others) so that this could not happen. This is hard and looks like an easy pitfall to me.

I think the good solution is either:

  • WebSocketHandler should fixed to not throw. E.g. not check WebSocket.Status in the main part (it does again in a task), or check it inside a try..catch.
  • or WebSocket.Status should not throw even when disposed. It can return an appropriate status instead.

ReceiveAsync cancellation throws WebSocketException and terminates the socket

await Socket.ReceiveAsync( new ArraySegment( Buffer ), Ct );
cannot be cancelled on a ClientWebSocket when Ct is the CancellationToken.
Instead of throwing a OperationCanceledException and keeping the socket alive, the following exception is thrown and the socket is aborted:

System.Net.WebSockets.WebSocketException: The 'System.Net.WebSockets.InternalClientWebSocket' instance cannot be used for communication because it has been transitioned into the 'Aborted' state. ---> System.Net.Http.WinHttpException: The operation has been canceled

This is true for both the ClientWebSocket and on a server socket when WebListener is used.
When Kestrel is used, ReceiveAsync CAN be cancelled on the SERVER, the cancellation takes about 10 seconds though.

Minimal solution with both the client and server part to reproduce on Stack Overflow: http://stackoverflow.com/questions/34634652/dnx-core-websocket-clientwebsocket-receiveasync-cancellation-is-not-working-p

WebsocketHandler.Send is sometimes not working

I am using the WebsocketHandler in an MVC application. On the client I am using WebsocketsSharp on the Unity3d platform. Everything works fine on the first / fresh launch. I boot up the server, I connect the client, and they communicate fine.

If I disconnect the client and reconnect it, things start breaking. Specifically calling the WebsocketHandler.Send method stops working. I can still send to the server from the client. I can still communicate with the client via using the WebsocketCollection.Broadcast() method.

I was wondering what I could do to debug this.

Did a little more debuging. Restarting the client does not help. In fact, sometimes restarting the server does not help. What does help is killing the IISExpress instance. That will guarantee the issue 'is resolved' (at least until I disconnect again).

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.