[英]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.