# 機能設計書 104-Sockets

## 概要

本ドキュメントは、Julia標準ライブラリ `Sockets` モジュールが提供するネットワークソケット通信機能の設計を記述する。`TCPSocket`、`UDPSocket`、`IPAddr`（IPv4/IPv6）を中心に、TCP/UDP通信、DNS解決、マルチキャスト等のネットワーク機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Juliaプログラムからのネットワーク通信を可能にする基盤機能。TCPクライアント/サーバー、UDP送受信、DNS名前解決等、一般的なネットワークプログラミングに必要な機能を提供する。libuv ライブラリをバックエンドとして使用し、非同期I/Oモデルに基づく効率的な通信を実現する。

**機能の利用シーン**：HTTPサーバー/クライアントの基盤、分散計算のプロセス間通信、リアルタイムデータ受信、マイクロサービス間通信、IoTデバイスとの通信。

**主要な処理内容**：
1. IPアドレス型（IPv4/IPv6/InetAddr）の定義とパース
2. TCP接続（connect/listen/accept/bind）
3. UDP通信（send/recv/recvfrom）
4. DNS解決（getaddrinfo/getalladdrinfo/getnameinfo）
5. マルチキャスト（join_multicast_group/leave_multicast_group）
6. ソケットオプション（nagle/quickack/setopt）
7. PipeServer（Unixドメインソケット）

**関連システム・外部連携**：libuv（非同期I/Oライブラリ）、Base.LibuvStream/LibuvServer。

**権限による制御**：OSレベルのネットワークアクセス権限に依存。特権ポート（1024未満）へのbindはroot権限が必要。

## 関連画面

本機能に直接関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | バックエンド通信基盤として利用 |

## 機能種別

データ連携 / 通信処理

## 入力仕様

### 入力パラメータ（TCP接続）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| host | AbstractString / IPAddr | Yes | 接続先ホスト名またはIPアドレス | DNS解決可能であること |
| port | Integer | Yes | 接続先ポート番号 | 0-65535 |
| backlog | Integer | No | listen時の待機キューサイズ（デフォルト511） | 正の整数 |

### 入力パラメータ（UDP送信）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| socket | UDPSocket | Yes | 送信元ソケット | StatusInit/StatusOpen/StatusActive |
| host | IPAddr | Yes | 送信先IPアドレス | IPv4またはIPv6 |
| port | Integer | Yes | 送信先ポート番号 | 0-65535 |
| msg | Any | Yes | 送信データ | write可能なデータ |

### 入力データソース

ネットワークソケット（OS経由）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tcp_connection | TCPSocket | TCP接続確立後のソケット |
| udp_data | Vector{UInt8} | UDP受信データ |
| sender_addr | InetAddr | UDP送信元アドレス |
| resolved_addr | IPAddr | DNS解決結果 |

### 出力先

ネットワーク（OS経由）。

## 処理フロー

### 処理シーケンス（TCPサーバー）

```
1. listen(host, port) で待ち受け開始
   ├─ TCPServer() 生成
   ├─ bind(sock, host, port) でアドレスバインド
   └─ uv_listen() で待ち受け開始
2. accept(server) でクライアント接続受付
   ├─ uv_accept() で接続受理
   └─ TCPSocket を返却
3. read/write で通信
4. close で終了
```

### フローチャート

```mermaid
flowchart TD
    subgraph TCPサーバー
    A["listen(host, port)"] --> B["TCPServer() 生成"]
    B --> C["bind(sock, host, port)"]
    C --> D["uv_listen()"]
    D --> E["accept(server)"]
    E --> F["TCPSocket（接続済み）"]
    end
    subgraph TCPクライアント
    G["connect(host, port)"] --> H["TCPSocket() 生成"]
    H --> I["getaddrinfo(host)"]
    I --> J["connect!(sock, addr, port)"]
    J --> K["wait_connected(sock)"]
    K --> L["TCPSocket（接続済み）"]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-104-1 | ソケット状態管理 | StatusUninit -> StatusInit -> StatusOpen/StatusConnecting -> StatusActive/StatusClosed の状態遷移 | 全ソケット操作 |
| BR-104-2 | IOロック | iolock_begin/iolock_end でスレッドセーフなIO操作 | 全libuv操作 |
| BR-104-3 | バックログデフォルト | listen()のデフォルトbacklogは511 | listen呼び出し時 |
| BR-104-4 | 遅延ソケット生成 | TCPSocket(delay=true)でbindまでfdの生成を遅延 | デフォルト動作 |
| BR-104-5 | ポート範囲 | ポート番号は0-65535の範囲 | connect!/bind時にArgumentError |

### 計算ロジック

- IPアドレスのバイトオーダー変換: `hton`/`ntoh` によるネットワークバイトオーダー変換
- アドレスファミリ判定: `jl_sockaddr_is_ip4`/`jl_sockaddr_is_ip6` によるアドレス型判定

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EADDRINUSE | IOError | アドレスが既に使用中 | 別ポートを使用するか、reuseaddr=trueを指定 |
| UV_EACCES | IOError | アクセス権不足 | 適切な権限で実行 |
| UV_EADDRNOTAVAIL | IOError | アドレスが利用不可 | 正しいアドレスを指定 |
| UV_ECONNABORTED | IOError | 接続が中断された | 再接続を試みる |
| UV_EAGAIN | IOError | リソースが一時的に利用不可 | 内部的にリトライ |

### リトライ仕様

- `accept` は内部的に `UV_EAGAIN` 時に自動リトライ（wait/notifyメカニズム）
- `listenany` はポートが使用中の場合にポート番号を+1しつつリトライ

## トランザクション仕様

該当なし。

## パフォーマンス要件

- Nagle's algorithmの制御: `nagle(sock, true/false)` で遅延バッチングを有効/無効化
- TCP_QUICKACK: `quickack(sock, true)` でLinux環境でのACK遅延を最小化
- UDPバッファ: 64KBの固定サイズバッファ（libuv標準）、16KB以上の無駄がない場合はunsafe_wrapで再利用

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

- ネットワーク通信は暗号化されない（TLS/SSLはMbedTLS.jl等の外部パッケージが必要）
- reuseaddr=trueはポートハイジャックのリスクがある
- DNSスプーフィングに対する保護はない

## 備考

- IPv6のみモード: `ipv6only=true` でデュアルスタックを無効化可能
- PipeServer: Unixドメインソケット（名前付きパイプ）もサポート（`PipeServer.jl` で実装）
- AF_INET6の値はOSにより異なる（Linux=10, macOS=30, Windows=23）

---

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

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IPAddr.jl | `stdlib/Sockets/src/IPAddr.jl` | `IPv4`/`IPv6` 構造体: IPアドレスのデータ表現。UInt32/UInt128 |
| 1-2 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `TCPSocket` 構造体（58-82行目）: handle, status, buffer, cond等のフィールド |
| 1-3 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `TCPServer` 構造体（113-127行目）: サーバーソケット |
| 1-4 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `UDPSocket` 構造体（179-202行目）: UDPソケット |

**読解のコツ**: SocketsモジュールはBaseの `LibuvStream` / `LibuvServer` を継承している。状態管理は `StatusUninit`/`StatusInit`/`StatusOpen`/`StatusActive`/`StatusClosing`/`StatusClosed` の列挙値で管理される。

#### Step 2: TCP接続フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `connect!(sock, host, port)`（568-575行目）: DNS解決+TCP接続開始 |
| 2-2 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `connect!(sock, host::IPAddr, port)`（511-526行目）: libuv経由の接続開始 |
| 2-3 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `wait_connected(x)`（530-551行目）: 接続完了待ち |
| 2-4 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `listen(addr; backlog)`（638-643行目）: サーバー起動 |
| 2-5 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `accept(server, client)`（699-725行目）: クライアント接続受付 |

#### Step 3: UDP通信フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `send(sock, ipaddr, port, msg)`（441-473行目）: UDP送信 |
| 3-2 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `recvfrom(sock)`（346-370行目）: UDP受信 |
| 3-3 | Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | `uv_recvcb`（374-419行目）: libuvコールバックでの受信処理 |

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

```
connect(host, port)  [TCP クライアント]
    ├─ TCPSocket() -> uv_tcp_init_ex
    ├─ getaddrinfo(host) -> uv_getaddrinfo
    ├─ connect!(sock, addr, port) -> jl_tcp_connect
    └─ wait_connected(sock)

listen(host, port)  [TCP サーバー]
    ├─ TCPServer() -> uv_tcp_init_ex
    ├─ bind(sock, host, port) -> jl_tcp_bind
    └─ uv_listen(sock, backlog, uv_connectioncb)

accept(server)
    ├─ accept_nonblock(server, client) -> uv_accept
    └─ wait(server.cond)  [接続待ち]

send(sock, addr, port, msg)  [UDP 送信]
    └─ _send_async(sock, addr, port, buf) -> jl_udp_send

recvfrom(sock)  [UDP 受信]
    ├─ uv_udp_recv_start
    └─ wait(sock.recvnotify) -> uv_recvcb コールバック
```

### データフロー図

```
[TCPクライアント]
 host:port ──▶ getaddrinfo() ──▶ IPAddr ──▶ connect!() ──▶ TCPSocket(Open)
                                                                │
                                                      write/read ──▶ データ送受信

[TCPサーバー]
 host:port ──▶ bind() ──▶ listen() ──▶ accept() ──▶ TCPSocket(Open)
                                                          │
                                                write/read ──▶ データ送受信

[UDP通信]
 UDPSocket ──▶ send(addr, port, data) ──▶ ネットワーク
 UDPSocket ──▶ recvfrom() ◀── ネットワーク ──▶ (InetAddr, data)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Sockets.jl | `stdlib/Sockets/src/Sockets.jl` | ソース | メインモジュール（TCP/UDP/listen/connect/accept） |
| IPAddr.jl | `stdlib/Sockets/src/IPAddr.jl` | ソース | IPv4/IPv6/InetAddr型定義 |
| addrinfo.jl | `stdlib/Sockets/src/addrinfo.jl` | ソース | DNS解決（getaddrinfo等） |
| PipeServer.jl | `stdlib/Sockets/src/PipeServer.jl` | ソース | Unixドメインソケット |
