React and ASP.NET Core プロジェクトでWebSocket が繋がらない [解決]
Q&A
Closed
解決したいこと
Visual Studio 2022 Version 17.8 を利用してWebアプリを作っています。
Version 17.8 で新たに使えるようになった "React and ASP.NET Core" テンプレート (JavaScript用) を用いて新規作成したプロジェクトに対して、サーバ側・クライアント側でWebSocket通信のコード追加をしても、WebSocket接続がされない問題が発生しています。解決方法を教えてください。
なお、WebSocketの利用は下記のMicrosoft情報を参考にしています。
発生している問題
サーバー側に WebSocket の要求の受け入れ処理のコードを追加し、クライアント側に WebSocket の接続要求のコードを追加して実行するが、反応がない。
自分で試したこと (再現手順)
[手順1] Visual Studio 2022 (Version 17.8以降) を用いて "React and ASP.NET Core" プロジェクト (JavaScript) を新規作成します。
[手順2] サーバー側プロジェクトにある Program.cs に WebSocket接続要求を受け付けて、そのまま受信メッセージを送り返すコードを追加します。
//--- ここから追加
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
// WebSocket通信要求を受理する
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
Console.WriteLine("WebSocket接続要求を受付");
// メッセージを受け取る
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
// そのメッセージが通信クローズを意図したものではないならば...
while (!receiveResult.CloseStatus.HasValue)
{
// そのメッセージをそのまま送り返す
await webSocket.SendAsync(
new ArraySegment<byte>(buffer, 0, receiveResult.Count),
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None);
// 次のメッセージを受け取る
receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
}
// WebSocket通信をクローズする
await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None);
}
else
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
else
{
await next(context);
}
});
//--- ここまで追加
[手順3] クライアント側プロジェクトにある ./src/App.jsx に WebSocket接続を要求し、簡単なメッセージ送受信するコードを追加します。
//--- ここから追加
var scheme = document.location.protocol === "https:" ? "wss" : "ws";
var port = document.location.port ? (":" + document.location.port) : "";
var url = scheme + "://" + document.location.hostname + port + "/ws";
const socket = new WebSocket(url);
console.log(`WebSocket connecting (URL: ${url}) ...`)
socket.onopen = () => { console.log('WebSocket openned'); socket.send('Hello, world!'); }
socket.onmessage = (ev) => console.log('WebSocket received: ' + ev.data);
socket.onerror = () => console.log('WebSocket error');
socket.onclose = (ev) => console.log(`WebSocket closed: ${ev.reason} (Code: ${ev.code})`);
//--- ここまで追加
[手順4] Visual Studio 2022 でデバッグの開始 (F5 キーを押下) する。Vsiual Studio 2022 の「出力」ウィンドウに "WebSocket connecting..." と表示され、クライアント側で WebSocket オブジェクトが生成され、WebSocket 接続の要求をしているが、このまま何の変化もなく接続が成立しないままとなる。
そして4分間が経過したところで、エラーとなり接続 (接続要求) が Code 1006 で異常クローズする。
WebSoceket エラーコード を下記で参照したところ、Code 1006は「予約済み。ステータスコードが期待される接続が異常終了した(close frame が送信されない)ことを示す。」とある。おそらく、4分間経過してのタイムアウトエラーの意味と推測。