簡體   English   中英

帶有WebSocket的ASP.NET Core-永遠不會發生WebSocket握手

[英]ASP.NET Core with WebSockets - WebSocket handshake never occurs

我是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類Configure方法的代碼段:

        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

我已經能夠回答我自己的問題。 因此,在我僅提供了一個代碼段的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;

就是這樣,它有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM