# 機能設計書: System.Net.WebSockets（WebSocket通信）

## 1. 機能概要

### 1.1 機能名
System.Net.WebSockets（WebSocket通信）

### 1.2 機能ID
FUNC-014

### 1.3 機能説明
.NET ランタイムにおけるWebSocketプロトコル（RFC 6455）通信機能を提供するライブラリ。双方向リアルタイム通信を実現し、クライアント・サーバー間で低遅延のメッセージ交換を可能にする。テキストおよびバイナリメッセージの送受信、Keep-Alive、クローズハンドシェイクなど、WebSocketプロトコルの完全なサポートを提供する。

### 1.4 関連画面
- なし（基盤ライブラリのため直接的な関連画面は存在しない）

## 2. 機能要件

### 2.1 入力仕様

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| uri | Uri | Yes | WebSocket接続先URI（ws:// または wss://） |
| buffer | ArraySegment<byte>/Memory<byte> | Yes | 送受信バッファ |
| messageType | WebSocketMessageType | Yes | メッセージタイプ（Text/Binary） |
| endOfMessage | bool | Yes | メッセージ終端フラグ |
| closeStatus | WebSocketCloseStatus | No | クローズステータス |
| cancellationToken | CancellationToken | No | キャンセルトークン |

### 2.2 出力仕様

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| WebSocketReceiveResult | WebSocketReceiveResult | 受信結果（サイズ、タイプ、終端フラグ） |
| ValueWebSocketReceiveResult | ValueWebSocketReceiveResult | 値型受信結果（高パフォーマンス） |
| WebSocketState | WebSocketState | 接続状態 |
| WebSocketCloseStatus | WebSocketCloseStatus | クローズ理由 |

### 2.3 処理フロー

```
ClientWebSocket.ConnectAsync(uri)
    │
    ▼
┌─────────────────────┐
│ HTTP Upgrade要求    │
│ Sec-WebSocket-Key   │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ 101 Switching       │
│ Protocols           │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ WebSocket接続確立    │
│ State: Open         │
└─────────────────────┘
    │
    ├───────────────────────┐
    ▼                       ▼
SendAsync()           ReceiveAsync()
    │                       │
    ▼                       ▼
┌─────────────────────┐
│ フレーム送受信       │
│ マスキング処理       │
└─────────────────────┘
    │
    ▼
CloseAsync()
    │
    ▼
┌─────────────────────┐
│ クローズハンドシェイク │
│ State: Closed        │
└─────────────────────┘
```

## 3. 詳細設計

### 3.1 クラス構成

#### 3.1.1 主要クラス

| クラス名 | 責務 |
|----------|------|
| WebSocket | WebSocket通信の抽象基底クラス |
| ClientWebSocket | クライアント側WebSocket実装 |
| ManagedWebSocket | .NETマネージド実装 |
| WebSocketReceiveResult | 受信操作の結果 |
| ValueWebSocketReceiveResult | 値型の受信結果（アロケーション削減） |
| WebSocketCreationOptions | WebSocket作成オプション |

### 3.2 WebSocket 抽象クラス（WebSocket.cs）

#### 3.2.1 プロパティ

```csharp
public abstract WebSocketCloseStatus? CloseStatus { get; }
public abstract string? CloseStatusDescription { get; }
public abstract string? SubProtocol { get; }
public abstract WebSocketState State { get; }
```

#### 3.2.2 主要メソッド

```csharp
// 送信
public abstract Task SendAsync(
    ArraySegment<byte> buffer,
    WebSocketMessageType messageType,
    bool endOfMessage,
    CancellationToken cancellationToken);

public virtual ValueTask SendAsync(
    ReadOnlyMemory<byte> buffer,
    WebSocketMessageType messageType,
    bool endOfMessage,
    CancellationToken cancellationToken);

// 受信
public abstract Task<WebSocketReceiveResult> ReceiveAsync(
    ArraySegment<byte> buffer,
    CancellationToken cancellationToken);

public virtual ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(
    Memory<byte> buffer,
    CancellationToken cancellationToken);

// クローズ
public abstract Task CloseAsync(
    WebSocketCloseStatus closeStatus,
    string? statusDescription,
    CancellationToken cancellationToken);

public abstract Task CloseOutputAsync(
    WebSocketCloseStatus closeStatus,
    string? statusDescription,
    CancellationToken cancellationToken);

// 中断
public abstract void Abort();
```

### 3.3 ClientWebSocket クラス

#### 3.3.1 接続オプション（ClientWebSocketOptions）

| プロパティ | 型 | 説明 |
|------------|------|------|
| SetRequestHeader | メソッド | カスタムヘッダー追加 |
| AddSubProtocol | メソッド | サブプロトコル追加 |
| Credentials | ICredentials | 認証情報 |
| Proxy | IWebProxy | プロキシ設定 |
| Cookies | CookieContainer | クッキー |
| KeepAliveInterval | TimeSpan | Keep-Alive間隔 |
| DangerousDeflateOptions | WebSocketDeflateOptions | 圧縮オプション |

#### 3.3.2 接続

```csharp
public Task ConnectAsync(Uri uri, CancellationToken cancellationToken);
public Task ConnectAsync(Uri uri, HttpMessageInvoker? invoker, CancellationToken cancellationToken);
```

### 3.4 WebSocketState 列挙型

| 状態 | 値 | 説明 |
|------|-----|------|
| None | 0 | 初期状態 |
| Connecting | 1 | 接続中 |
| Open | 2 | 接続済み |
| CloseSent | 3 | クローズ送信済み |
| CloseReceived | 4 | クローズ受信済み |
| Closed | 5 | 完全にクローズ |
| Aborted | 6 | 中断 |

### 3.5 WebSocketCloseStatus 列挙型

| ステータス | 値 | 説明 |
|------------|-----|------|
| NormalClosure | 1000 | 正常終了 |
| EndpointUnavailable | 1001 | エンドポイント離脱 |
| ProtocolError | 1002 | プロトコルエラー |
| InvalidMessageType | 1003 | 不正なメッセージタイプ |
| Empty | 1005 | ステータスなし |
| InvalidPayloadData | 1007 | 不正なペイロード |
| PolicyViolation | 1008 | ポリシー違反 |
| MessageTooBig | 1009 | メッセージ過大 |
| MandatoryExtension | 1010 | 必須拡張なし |
| InternalServerError | 1011 | サーバー内部エラー |

### 3.6 静的ファクトリメソッド

```csharp
// Streamからの作成（WebSocket.cs: 132-154行目）
public static WebSocket CreateFromStream(
    Stream stream,
    bool isServer,
    string? subProtocol,
    TimeSpan keepAliveInterval);

public static WebSocket CreateFromStream(
    Stream stream,
    WebSocketCreationOptions options);

// バッファ作成ヘルパー
public static ArraySegment<byte> CreateClientBuffer(
    int receiveBufferSize,
    int sendBufferSize);

public static ArraySegment<byte> CreateServerBuffer(
    int receiveBufferSize);
```

### 3.7 Keep-Alive設定

```csharp
// デフォルト間隔（WebSocket.cs: 84-88行目）
public static TimeSpan DefaultKeepAliveInterval
{
    get { return WebSocketDefaults.DefaultClientKeepAliveInterval; }
}
```

## 4. エラー処理

### 4.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| WebSocketException | WebSocketプロトコルエラー |
| InvalidOperationException | 不正な状態での操作 |
| ObjectDisposedException | Dispose後の操作 |
| ArgumentNullException | 必須引数がnull |
| ArgumentOutOfRangeException | バッファサイズが不正 |
| OperationCanceledException | キャンセルされた |

### 4.2 WebSocketError 列挙型

| エラー | 説明 |
|--------|------|
| Success | 成功 |
| InvalidMessageType | 不正なメッセージタイプ |
| Faulted | 障害 |
| NativeError | ネイティブエラー |
| NotAWebSocket | WebSocketでない |
| UnsupportedVersion | 未サポートバージョン |
| UnsupportedProtocol | 未サポートプロトコル |
| HeaderError | ヘッダーエラー |
| ConnectionClosedPrematurely | 予期せぬ切断 |
| InvalidState | 不正な状態 |

### 4.3 状態検証

```csharp
// 状態検証ヘルパー（WebSocket.cs: 90-108行目）
protected static void ThrowOnInvalidState(
    WebSocketState state,
    params WebSocketState[] validStates);

protected static bool IsStateTerminal(WebSocketState state) =>
    state == WebSocketState.Closed || state == WebSocketState.Aborted;
```

## 5. セキュリティ考慮事項

### 5.1 TLS/SSL
- `wss://` スキームでTLS接続
- 証明書検証のカスタマイズ可能

### 5.2 認証
- HTTP Upgradeリクエストでの認証ヘッダー
- Cookie による認証
- Basic/Bearer認証

### 5.3 入力検証
- メッセージサイズの制限
- UTF-8テキスト検証（テキストメッセージ）

## 6. コードリーディングガイド

### 6.1 推奨読解順序

1. **データ構造の理解**
   - `WebSocketState.cs`: 接続状態の定義
   - `WebSocketCloseStatus.cs`: クローズステータスの定義
   - `WebSocketMessageType.cs`: メッセージタイプの定義

2. **エントリーポイント**
   - `WebSocket.cs`: 抽象基底クラス
   - **13-33行目**: 抽象プロパティとメソッドの宣言
   - **35-54行目**: Memory<byte>ベースのReceiveAsync仮想実装
   - **84-88行目**: DefaultKeepAliveInterval プロパティ
   - **132-154行目**: CreateFromStream ファクトリメソッド

3. **クライアント実装**
   - `ClientWebSocket.cs`: クライアントWebSocket
   - `ClientWebSocketOptions.cs`: 接続オプション

4. **内部実装**
   - `ManagedWebSocket.cs`: マネージドWebSocket実装
   - `WebSocketValidate.cs`: バリデーション

### 6.2 プログラム呼び出し階層図

```
ClientWebSocket.ConnectAsync(uri, ct)
    │
    ├── Options検証
    │
    ├── HTTP Upgrade リクエスト構築
    │       │
    │       ├── Sec-WebSocket-Key生成
    │       ├── Sec-WebSocket-Version: 13
    │       └── カスタムヘッダー追加
    │
    ├── HttpClient.SendAsync() [Upgrade要求]
    │       │
    │       └── 101 Switching Protocols待ち
    │
    └── ManagedWebSocket生成
            │
            └── State = Open

SendAsync(buffer, messageType, endOfMessage, ct)
    │
    ├── 状態検証 (State == Open)
    │
    ├── フレーム構築
    │       │
    │       ├── Opcode設定
    │       ├── マスキング（クライアント）
    │       └── ペイロード長設定
    │
    └── Stream.WriteAsync()

ReceiveAsync(buffer, ct)
    │
    ├── 状態検証
    │
    ├── Stream.ReadAsync()
    │       │
    │       └── フレームヘッダー解析
    │
    ├── ペイロード読み取り
    │       │
    │       └── アンマスキング（サーバー）
    │
    └── WebSocketReceiveResult生成
```

### 6.3 データフロー図

```
┌──────────────────┐
│ アプリケーション   │
│ ClientWebSocket  │
└────────┬─────────┘
         │
         ▼ ConnectAsync
┌──────────────────┐
│ HTTP Upgrade     │
│ 101 Switching    │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ ManagedWebSocket │
│ Stream管理       │
└────────┬─────────┘
         │
    ┌────┴────┐
    ▼         ▼
SendAsync  ReceiveAsync
    │         │
    ▼         ▼
┌──────────────────┐
│ WebSocketフレーム │
│ ├─ FIN bit      │
│ ├─ Opcode       │
│ ├─ MASK bit     │
│ ├─ Payload Len  │
│ └─ Payload      │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ TCP/TLS Stream   │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ リモートエンド    │
│ ポイント         │
└──────────────────┘
```

### 6.4 読解のコツ

#### 6.4.1 フレーム構造
WebSocketフレームは以下の構造:
```
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
```

#### 6.4.2 Memory<byte>対応
WebSocket.cs 35-54行目では、Memory<byte>ベースのReceiveAsyncがArraySegment版をラップ:
- ArrayPool<byte>を使用した効率的なバッファ管理
- MemoryMarshal.TryGetArray による最適化

#### 6.4.3 クライアント/サーバーの違い
- クライアント: マスキング必須
- サーバー: マスキング禁止
- CreateFromStream の isServer パラメータで制御

### 6.5 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs` | ソース | 抽象基底クラス |
| `src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs` | ソース | クライアント実装 |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs` | ソース | マネージド実装 |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketState.cs` | ソース | 状態列挙型 |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketCloseStatus.cs` | ソース | クローズステータス |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketMessageType.cs` | ソース | メッセージタイプ |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketReceiveResult.cs` | ソース | 受信結果 |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketCreationOptions.cs` | ソース | 作成オプション |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketException.cs` | ソース | 例外クラス |
| `src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketValidate.cs` | ソース | バリデーション |

## 7. 使用例

### 7.1 基本的な接続と送受信

```csharp
using var ws = new ClientWebSocket();
await ws.ConnectAsync(new Uri("wss://echo.websocket.org"), CancellationToken.None);

// 送信
var message = Encoding.UTF8.GetBytes("Hello, WebSocket!");
await ws.SendAsync(message, WebSocketMessageType.Text, true, CancellationToken.None);

// 受信
var buffer = new byte[1024];
var result = await ws.ReceiveAsync(buffer, CancellationToken.None);
var received = Encoding.UTF8.GetString(buffer, 0, result.Count);
Console.WriteLine($"Received: {received}");

// クローズ
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Done", CancellationToken.None);
```

### 7.2 受信ループ

```csharp
var buffer = new byte[4096];
while (ws.State == WebSocketState.Open)
{
    var result = await ws.ReceiveAsync(buffer, CancellationToken.None);

    if (result.MessageType == WebSocketMessageType.Close)
    {
        await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
        break;
    }

    var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
    Console.WriteLine($"Received: {message}");
}
```

### 7.3 カスタムヘッダー付き接続

```csharp
var ws = new ClientWebSocket();
ws.Options.SetRequestHeader("Authorization", "Bearer token123");
ws.Options.AddSubProtocol("graphql-ws");
ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(30);

await ws.ConnectAsync(new Uri("wss://api.example.com/ws"), CancellationToken.None);
```

## 8. テスト観点

### 8.1 単体テスト観点
- 接続・切断のライフサイクル
- テキスト/バイナリメッセージの送受信
- 大きなメッセージの分割送信
- 各種クローズステータスの処理
- 状態遷移の検証

### 8.2 結合テスト観点
- 実際のWebSocketサーバーとの通信
- TLS接続の検証
- プロキシ経由の接続
- 長時間接続の安定性

### 8.3 性能テスト観点
- メッセージスループット
- 同時接続数の影響
- メモリ使用量（バッファ管理）

## 9. 変更履歴

| バージョン | 日付 | 変更内容 |
|------------|------|----------|
| 1.0 | 2026-01-30 | 初版作成 |
