Socket Library
成熟度に関する注意: このライブラリは機能しており十分にテストされていますが、公開されたばかりです。開発、内部ツール、管理された環境での使用に適しています。信頼できないネットワーク入力を伴う本番環境へのデプロイは、コードベースが数か月間実際の環境で使用されてからにしてください。
POSIXシステム向けの高性能・例外駆動型ソケットツールキット。TCP、UDP、Unixドメインソケット、HTTP/1.1、HTTP/2、QUIC、WebSocket、TLS/DTLS向けに、クリーンでモダンなC APIを提供します。包括的なエラーハンドリング、ゼロコピーI/O、クロスプラットフォームのイベントポーリングを備えています。
機能
コアネットワーキング
- TCPストリームソケット - 高機能なTCPクライアント/サーバー、スキャッター/ギャザーI/O
- UDPデータグラムソケット - コネクションレスモードとコネクション指向モード、マルチキャスト/ブロードキャスト
- Unixドメインソケット - ピア資格情報サポート、ファイルディスクリプタ受け渡しを備えたIPCソケット
- TLS 1.3サポート - モダンなTLS、SNI、ALPN、セッション再開、CRL/OCSP、証明書ピンニング、Certificate Transparency(CT)、kTLSオフロード、0-RTT早期データ、KeyUpdate
- DTLS 1.2+サポート - クッキー交換によるDoS保護、セッションキャッシング、ALPNを備えたセキュアUDP
HTTPプロトコルスタック
- HTTP/1.1 - テーブル駆動型DFAパーサー(RFC 9112)、チャンク転送エンコーディング、リクエストスマグリング防止
- HTTP/2 - バイナリフレーミング、ストリーム多重化、フロー制御、サーバープッシュ(RFC 9113)
- HPACK - 静的/動的テーブルを用いたヘッダー圧縮、ハフマン符号化(RFC 7541)
- QPACK - HTTP/3ヘッダー圧縮(RFC 9204)、2ストリームアーキテクチャ、ブロックされたストリーム管理
- HTTPクライアント - コネクションプーリング、認証(Basic/Digest/Bearer)、クッキー(RFC 6265)
- HTTPサーバー - イベント駆動型リクエスト処理、キープアライブ、グレースフルシャットダウン
QUICトランスポート
- RFC 9000準拠 - 完全なQUIC v1トランスポートプロトコル実装
- コネクション管理 - コネクションIDローテーション、ステートレスリセット、アドレス検証
- ストリーム多重化 - 双方向および単方向ストリーム、フロー制御
- ロス検出 - RFC 9002輻輳制御およびロスリカバリ
- パスマイグレーション - ネットワーク変更に伴うシームレスなコネクション移行
- 0-RTT再開 - 早期データサポートによる高速再接続
QUIC-TLS(RFC 9001)
- パケット保護 - AEAD暗号化(AES-128-GCM、AES-256-GCM、ChaCha20-Poly1305)
- ヘッダー保護 - パケット番号暗号化のためのAES-ECB/ChaCha20マスク生成
- 鍵導出 - クライアントDCIDからのHKDFベースの初期秘密、ハンドシェイク/トラフィック鍵
- 鍵更新 - 鍵フェーズビットローテーション、AEAD秘匿性限界(RFC 9001 §6)
- 再送信インテグリティ - 再送信パケットのAEADタグ検証(RFC 9001 §5.8)
- トランスポートパラメータ - QUIC設定交換用TLS拡張(タイプ0x39)
QPACK(RFC 9204)
- ヘッダー圧縮 - HTTP/3ヘッダー圧縮による先頭ブロッキング回避
- 2ストリームアーキテクチャ - エンコーダーストリーム(0x02)とデコーダーストリーム(0x03)を分離
- 動的テーブル - 絶対インデックス方式、エンコーダー相対方式、フィールド相対方式
- 静的テーブル - 99の事前定義エントリ(RFC 9204 Appendix A)
- 状態同期 - セクション確認応答、ストリームキャンセル、挿入カウント増分
- ブロックされたストリーム管理 - SETTINGSネゴシエーションによる設定可能なブロックストリーム制限
WebSocket
- RFC 6455準拠 - 完全なWebSocketプロトコル実装
- permessage-deflate - zlibによる圧縮拡張(RFC 7692)
- インクリメンタルUTF-8 - DFAベースのテキストフレーム検証
- 自動Ping/Pong - タイマー統合による設定可能なハートビート
プロキシトンネリング
- HTTP CONNECT - Basic認証によるプロキシトンネリング
- SOCKS4/4a - レガシーSOCKSサポート
- SOCKS5 - RFC 1928/1929、ユーザー名/パスワード認証
- 非同期API - ステートマシンによるノンブロッキングプロキシ接続
イベントシステム
- クロスプラットフォームポーリング - epoll(Linux)、kqueue(BSD/macOS)、poll フォールバック
- エッジトリガーモード - 高性能なイベント通知
- 非同期I/O - io_uring(Linux 5.1+)、kqueue AIO(BSD/macOS)
- タイマー - ワンショットおよび繰り返し、O(log n)ミンヒープ
コネクション管理
- コネクションプーリング - ハッシュテーブルによるO(1)ルックアップ、コネクションごとのI/Oバッファ
- Happy Eyeballs - RFC 8305デュアルスタックIPv4/IPv6接続レーシング
- 自動再接続 - サーキットブレーカーパターンによる指数バックオフ
- グレースフルシャットダウン - タイムアウト保証付きプールドレイン用ステートマシン
セキュリティ強化
- SYNフラッド保護 - レピュテーションスコアリング、スロットリング、カーネル統合
- IP単位の追跡 - クライアントごとの接続制限とレート制限
- レート制限 - トークンバケットアルゴリズムによる接続数および帯域幅の制限
- リクエストスマグリング防止 - RFC準拠の厳格なHTTPパース
DNS解決
- 非同期リゾルバー - スレッドプールとクエリ多重化によるノンブロッキング解決
- DNS-over-TLS(DoT) - RFC 7858/8310暗号化DNS、機会主義的/厳格モード
- DNS-over-HTTPS(DoH) - RFC 8484 HTTPS経由のDNSクエリ(POST/GETメソッド)
- DNSSEC検証 - RFC 4033-4035信頼の連鎖、NSEC/NSEC3による認証された否定応答
- DNSクッキー - RFC 7873 EDNS0によるスプーフィング保護
- ネガティブキャッシング - RFC 2308に従った適切なNXDOMAIN/NODATA処理
- 拡張DNSエラー - RFC 8914詳細エラーコード
インフラストラクチャ
- 例外ベースのエラー -
TRY/EXCEPT/FINALLYによるクリーンなエラー伝搬
- シンプルAPI - 戻りコードベースの便利レイヤー(TRY/EXCEPT不要で一般的操作を実行)
- アリーナメモリ管理 - オーバーフロー保護付き効率的な割り当て
- 循環バッファI/O - ネットワーク操作のためのゼロコピーバッファリング
- 非同期I/O - プラットフォーム最適化された非同期操作(io_uring/kqueue)
- UTF-8検証 - WebSocketテキストフレーム向けセキュリティ重視のUTF-8処理
- 汎用リトライフレームワーク - ジッター付き指数バックオフによるレジリエントな操作
- IP単位の接続追跡 - クライアントIPごとの接続制限とレート制限
- ゼロコピーI/O - プラットフォーム最適化された
sendfile()とスキャッター/ギャザーI/O
- 可観測性 - プラグイン可能なロギング、Prometheus/StatsD/JSONメトリクスエクスポート、イベントディスパッチ
- 暗号ユーティリティ - SHA-1/256、HMAC、Base64、安全な乱数
プラットフォーム要件
- POSIX準拠システム(Linux、BSD、macOS)
- C11コンパイラ(GNU拡張あり)
- POSIXスレッド(pthread)によるスレッドセーフ操作
- カーネルのIPv6サポート(デュアルスタックソケット用)
- Windowsには非対応(Winsockアダプテーションレイヤーがない場合)
プラットフォーム固有の機能
| 機能 | Linux | BSD/macOS | フォールバック |
|---|
| イベントポーリング | epoll | kqueue | poll(2) |
| 非同期I/O | io_uring(5.1+) | kqueue AIO | エッジトリガー |
| TCP Fast Open | 3.7+ | 10.0+/10.11+ | 無効 |
| 輻輳制御 | 設定可能 | - | - |
| ピア資格情報 | SO_PEERCRED | LOCAL_PEERCRED | - |
| SYN保護 | TCP_DEFER_ACCEPT | SO_ACCEPTFILTER | ユーザースペース |
TLS/DTLS要件
- OpenSSL 1.1.1+ または LibreSSL(TLS 1.3対応)
- デフォルトでTLS 1.3のみ(設定可能)
- 安全なUDPには最低DTLS 1.2
クイックスタート
ビルド```bash
Basic build
cmake -S . -B build
cmake --build build -j
Run tests
cd build && ctest --output-on-failure
Build with TLS support (auto-detects OpenSSL/LibreSSL)
cmake -S . -B build -DENABLE_TLS=ON
Build with sanitizers for debugging
cmake -S . -B build -DENABLE_SANITIZERS=ON
Build with fuzzing support (requires Clang)
cmake -S . -B build -DENABLE_FUZZING=ON -DCMAKE_C_COMPILER=clang
### 基本的なTCPサーバー```c
#include "socket/Socket.h"
#include "core/Except.h"
#include <stdio.h>
int main(void)
{
Socket_T server = Socket_new(AF_INET, SOCK_STREAM, 0);
TRY
Socket_setreuseaddr(server);
Socket_bind(server, NULL, 8080);
Socket_listen(server, 128);
printf("Server listening on port 8080...\n");
while (1) {
Socket_T client = Socket_accept(server);
if (client) {
char buf[1024];
ssize_t n = Socket_recv(client, buf, sizeof(buf) - 1);
if (n > 0) {
buf[n] = '\0';
Socket_sendall(client, buf, n);
}
Socket_free(&client);
}
}
EXCEPT(Socket_Failed)
fprintf(stderr, "Error: %s\n", Socket_GetLastError());
END_TRY;
Socket_free(&server);
return 0;
}
基本的なTCPクライアント```c
#include "socket/Socket.h"
#include "core/Except.h"
#include <stdio.h>
#include <string.h>
int main(void)
{
Socket_T client = Socket_new(AF_INET, SOCK_STREAM, 0);
TRY
Socket_connect(client, "127.0.0.1", 8080);
printf("Connected to server\n");
const char *msg = "Hello, Server!";
Socket_sendall(client, msg, strlen(msg));
char buf[1024];
ssize_t n = Socket_recvall(client, buf, strlen(msg));
buf[n] = '\0';
printf("Received: %s\n", buf);
EXCEPT(Socket_Failed)
fprintf(stderr, "Error: %s\n", Socket_GetLastError());
EXCEPT(Socket_Closed)
fprintf(stderr, "Connection closed\n");
END_TRY;
Socket_free(&client);
return 0;
}
### 便利関数(ワンコールセットアップ)
一般的なユースケースでは、便利関数によりソケットのセットアップが簡素化されます:```c
#include "socket/Socket.h"
#include "socket/SocketDgram.h"
/* TCP Server - one call creates listening socket */
Socket_T server = Socket_listen_tcp("0.0.0.0", 8080, 128);
while (running) {
Socket_T client = Socket_accept_timeout(server, 1000); // 1s timeout
if (client) handle_client(client);
}
Socket_free(&server);
/* TCP Client with timeout - one call connects */
Socket_T client = Socket_connect_tcp("api.example.com", 443, 5000); // 5s timeout
Socket_sendall(client, request, len);
Socket_free(&client);