環境
サーバーはlocalhostにて実行しており、サーバー側とクライアント側は同一のマシンです。
マシン
- OS:Windows 10
- デバッグ環境:Visual Studio Community 2017
サーバー側
- フレームワーク:ASP.NET Core, .NET Core 2.0
クライアント側
- フレームワーク:.NET Framework 4.6.1
問題
WebSocketを用いたサーバー・クライアント間のデータのやりとりを実装しています。
クライアント側はClientWebSocket
を用いて実装していますが、ClientWebSocket.CloseAsync
を呼び出すとプログラムが進行しなくなってしまいます。以下にソースコードの関係の有りそうな箇所を掲載しますので、どこが間違っているか、もしくはCloseAsyncでプログラムが進行しなくなる時にありがちな事などご指摘いただけると助かります。
テスト用のプロジェクトでは再現しないため再現コードが書けずに申し訳ありませんが、再現するほうのプロジェクトでは以下のようなメソッド呼び出しでコネクションを閉じようとしています。大規模なコードであるため全ては載せられませんでした。
// クライアント側 if (WebSocket.State == WebSocketState.Open) { // このメソッド呼び出しが完了せず、プログラムが進行を停止する WebSocket.CloseAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "正常終了", CancellationToken.None).Wait(); }
サーバー側は以下のように応答します。
// サーバー側 // コネクションが確立したときに呼び出され、データの受信を待機するメソッド public async Task ListenConnectionAsync(OpenRoom room) { var buffer = new byte[1024 * 4]; // 接続していればリクエストを待つ while (room.Receiver.State == System.Net.WebSockets.WebSocketState.Open) { var result = await room.Receiver.ReceiveAsync( buffer: new ArraySegment<byte>(buffer), cancellationToken: CancellationToken.None); // 通常のデータ受信 if (result.MessageType == System.Net.WebSockets.WebSocketMessageType.Text) { // CastEventData はサーバー・クライアント間でやりとりするデータ try { var message = CastEventData.Deserialize(buffer, result.Count); await room.ReceiveAsync(message); } catch(Exception e) { Console.WriteLine(e); } } // コネクションを閉じるリクエストを受信した場合 else if(result.MessageType == System.Net.WebSockets.WebSocketMessageType.Close) { // コネクションを閉じるリクエストに応答する await room.Receiver.CloseOutputAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "正常終了", CancellationToken.None); break; } } } // CastEventData, CastDataはサーバー・クライアント間でやりとりするデータ public class OpenRoom { public string Name { get; set; } public CastData CastData { get; set; } public System.Net.WebSockets.WebSocket Receiver { get; set; } public List<System.Net.WebSockets.WebSocket> Senders { get; set; } internal Task ReceiveAsync(CastEventData message) { message.Event.Apply(CastData); // イベントに応じてサーバー上のデータを書き換える return Task.CompletedTask; } }
デバッグ内容
この問題について、ブレークポイントを置いてデバッグしています。クライアント側からコネクションを閉じるリクエストを送ると、サーバー側では「コネクションを閉じるリクエストに応答する」のコメントの部分が実行されました。これによってサーバーからクライアントへの応答もできているつもりなのですが、うまく行かず悩んでいるところです。
回答2件
あなたの回答
tips
プレビュー