質問編集履歴

2 デバッグした内容について追記

NumAniCloud

NumAniCloud score 48

2018/03/05 22:29  投稿

ClientWebSocket.CloseAsync メソッドが完了しない
# 環境
サーバーは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;
   }
}
```
```
## デバッグ内容
この問題について、ブレークポイントを置いてデバッグしています。クライアント側からコネクションを閉じるリクエストを送ると、サーバー側では「コネクションを閉じるリクエストに応答する」のコメントの部分が実行されました。これによってサーバーからクライアントへの応答もできているつもりなのですが、うまく行かず悩んでいるところです。
  • C#

    11241 questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET

    713 questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • WebSocket

    240 questions

    WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

1 再現するプロジェクトのソースコードであることを明記。

NumAniCloud

NumAniCloud score 48

2018/03/04 18:48  投稿

ClientWebSocket.CloseAsync メソッドが完了しない
# 環境
サーバーは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;
   }
}
```
  • C#

    11241 questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET

    713 questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • WebSocket

    240 questions

    WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る