带有WebSockets的ASP.NET Core - 永远不会发生WebSocket握手

时间:2017-09-27 21:42:23

标签: c# asp.net websocket

我是C#编程的新手,之前只使用过Java。我正在建设的这个项目应该非常简单 - 我们有一个网页,其中包含一系列外币对。选择的元素被发送到服务器,服务器以其汇率的硬编码值进行响应。要求是两个操作都是通过使用WebSockets实现的。这是我页面上的JS代码:

var protocol;
var wsUri;
var socket;

window.onload = function(e) {
    e.preventDefault();



    protocol = location.protocol === "https:" ? "wss:" : "ws:";
    wsUri = protocol + "//" + window.location.host;
    socket = new WebSocket(wsUri);

    socket.onopen = e => {
        console.log("socket opened", e);
    };

    document.getElementById("currencypair").onchange = function()
    {
        var selector = document.getElementById("currencypair");
        var text = selector.options[selector.selectedIndex].text;
        socket.send(text);
    };

    socket.onmessage = function (evt) {
        var receivedMessage = evt.data;
        document.getElementById("output").html(receivedMessage);
    };


};

以下是Startup.cs类配置方法的片段:

        app.UseWebSockets();
        app.UseMiddleware<WebSocketMiddleware>();

这是处理请求的中间件类。

public class WebSocketMiddleware
{

    private readonly RequestDelegate _next;

    public WebSocketMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            await _next.Invoke(context);
            return;
        }

        var ct = context.RequestAborted;
        using (var socket = await context.WebSockets.AcceptWebSocketAsync())
        {
            while (true)
            {
                var stringReceived = await ReceiveStringAsync(socket, ct);

                if (CurrencyPairCollection.CurrencyPairs.TryGetValue(stringReceived, out var value))
                {
                    await SendStringAsync(socket, value.ToString(), ct);
                }
                else
                {
                    throw new Exception("Unexpected value");
                }
                await Task.Delay(1000, ct);
            }
        }

    }

    private static async Task<string> ReceiveStringAsync(WebSocket socket, CancellationToken ct = default(CancellationToken))
    {
        var buffer = new ArraySegment<byte>();
        using (var ms = new MemoryStream())
        {
            WebSocketReceiveResult result;
            do
            {
                ct.ThrowIfCancellationRequested();

                result = await socket.ReceiveAsync(buffer, ct);
                ms.Write(buffer.Array, buffer.Offset, result.Count);
            }
            while (!result.EndOfMessage);

            ms.Seek(0, SeekOrigin.Begin);
            if (result.MessageType != WebSocketMessageType.Text || result.Count.Equals(0))
            {
                throw new Exception("Unexpected message");
            }

            using (var reader = new StreamReader(ms, Encoding.UTF8))
            {
                return await reader.ReadToEndAsync();
            }
        }
    }

    private static Task SendStringAsync(WebSocket socket, string data, CancellationToken ct = default(CancellationToken))
    {
        var segment = new ArraySegment<byte>(Encoding.UTF8.GetBytes(data));
        return socket.SendAsync(segment, WebSocketMessageType.Text, true, ct);
    }

}

请注意我正在使用以下示例,其中包含评论部分中人员列出的错误。我尽力解决它们,但由于我的经验有限,这可能是故障的所在。

https://www.softfluent.com/blog/dev/Using-Web-Sockets-with-ASP-NET-Core

基本上,在运行应用程序时,浏览器控制台会立即报告: 与'ws:// localhost:51017 /'的WebSocket连接失败:WebSocket握手期间出错:意外响应代码:200

1 个答案:

答案 0 :(得分:0)

我能够回答我自己的问题。所以在Startup.cs中,我只提供了一个片段,在我已经共享的行之前调用app.UseMvc()。这是由默认模板生成的。诀窍是将此调用移至以下内容:

    app.UseWebSockets();
    app.UseMiddleware<WebSocketMiddleware>();

否则请求管道中断。

这将允许我们的套接字打开,但不会更改异步任务ReceiveStringAsync(...)中的以下行

var buffer = new ArraySegment<byte>();

var buffer = new ArraySegment<byte>(new byte[8192]);

它仍然会过早关闭。接下来,只需要纠正JS语法错误。改变

document.getElementById("output").html(receivedMessage);

document.getElementById("output").value = receivedMessage;

这就是它,它有效。