Ton*_*ony 21 c# websocket asp.net-mvc-4 signalr asp.net-web-api
在ASP.NET Web API应用程序中使用原始websockets的首选方法是什么?
我们想在ASP.NET Web API应用程序的几个接口上使用二进制 WebSockets.我很难确定应该如何完成这项工作,因为.NET似乎存在多个在线冲突和/或过时的实现.
有这似乎是ASP.NET这样的例子一个,但我认为必须有在Web API框架内使用WebSockets的手段.据我所知,你可以在WebAPI中使用Signalr.
我以为使用Microsoft.AspNet.SignalR.WebSockets.WebSocketHandler会起作用,但我不确定如何将WebSocketHandler链接到Controller ......
class MyServiceController : ApiController
{
    [HttpGet]
    public HttpResponseMessage SwitchProtocols (string param)
    {
        HttpContext currentContext = HttpContext.Current;
        if (currentContext.IsWebSocketRequest || 
            currentContext.IsWebSocketRequestUpgrading)
        {
            // several out-dated(?) examples would 
            // use 'new MySocketHandler' for ???
            var unknown = new ????
            currentContext.AcceptWebSocketRequest(unknown); 
            return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
        }   
    }
}
class MySocketHandler : WebSocketHandler
{
    public MySocketHandler(): base(2048){}
    ...
}
不幸的是,AcceptWebSocketRequest不再接受WebSocketHandler,而是它的新签名是......
public void AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc)
有没有人在ASP.NET Web API应用程序中有最新的实现原始websockets的链接或快速示例?
Ton*_*ony 14
更新:在我和同事进行了一些研究之后,我们得出结论,WebSocketHandler类似乎并不打算在SignalR的内部进程之外使用.因为没有明显的手段来利用与SignalR隔离的WebSocketHandler.这很不幸,因为我发现它的接口比System.Web/System.Net接口略高一些.此外,下面描述的方法使用HttpContext,我认为应该避免使用它.
因此,我们计划采用类似于Mrchief所示的方法,但具有更多的Web API风格.像这样......(注意:我们的套接字是只写的,但是我发现你必须执行你希望WebSocket.State正确更新的读操作.
class MyServiceController : ApiController
{
    public HttpResponseMessage Get (string param)
    {
        HttpContext currentContext = HttpContext.Current;
        if (currentContext.IsWebSocketRequest || 
            currentContext.IsWebSocketRequestUpgrading)
        {
            currentContext.AcceptWebSocketRequest(ProcessWebsocketSession); 
            return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
        }   
    }
    private async Task ProcessWebsocketSession(AspNetWebSocketContext context)
    {
        var ws = context.WebSocket;
        new Task(() =>
        {
            var inputSegment = new ArraySegment<byte>(new byte[1024]);
            while (true)
            {
                // MUST read if we want the state to get updated...
                var result = await ws.ReceiveAsync(inputSegment, CancellationToken.None);
                if (ws.State != WebSocketState.Open)
                {
                    break;
                }
            }
        }).Start();
        while (true)
        {
            if (ws.State != WebSocketState.Open)
            {
                break;
            }
            else
            {
                byte[] binaryData = { 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe };
                var segment = new ArraySegment<byte>(binaryData);
                await ws.SendAsync(segment, WebSocketMessageType.Binary, 
                    true, CancellationToken.None);
            }
        }
    }
}
注意:显然错误检查和CancellationToken的正确使用留给读者练习.
Ren*_*ers 12
这是一个较老的问题,但我想补充一点.
事实证明,你可以使用它,我不知道他们为何如此"隐藏"它.如果有人可以向我解释这门课有什么问题,或者我在这里做的事情是某种"禁止"或"糟糕的设计",那会很好.
如果我们查看Microsoft.Web.WebSockets.WebSocketHandler,我们找到这个公共方法:
[EditorBrowsable(EditorBrowsableState.Never)]
public Task ProcessWebSocketRequestAsync(AspNetWebSocketContext webSocketContext);
这个方法对intellisense是隐藏的,但是它存在,并且可以在没有编译错误的情况下调用.
我们可以使用此方法来获取我们需要在AcceptWebSocketRequest方法中返回的任务.看一下这个:
public class MyWebSocketHandler : WebSocketHandler
{
    private static WebSocketCollection clients = new WebSocketCollection();
    public override void OnOpen()
    {
        clients.Add(this);
    }
    public override void OnMessage(string message)
    {
        Send("Echo: " + message);
    }
}
然后在我的API控制器中:
public class MessagingController : ApiController
{
    public HttpResponseMessage Get()
    {
        var currentContext = HttpContext.Current;
        if (currentContext.IsWebSocketRequest ||
            currentContext.IsWebSocketRequestUpgrading)
        {
            currentContext.AcceptWebSocketRequest(ProcessWebsocketSession);
        }
        return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
    }
    private Task ProcessWebsocketSession(AspNetWebSocketContext context)
    {
        var handler = new MyWebSocketHandler();
        var processTask = handler.ProcessWebSocketRequestAsync(context);
        return processTask;
    }
}
这完全没问题.OnMessage被触发,并回到我的JavaScript实例化的WebSocket ...