我是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
答案 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;
这就是它,它有效。