rust-network - 背景
歴史的経緯
インターネットプロトコルの発展
- パケット交換ネットワーク
- ノード間通信 - Vint Cerf, Bob Kahn
- 信頼性のある通信 - ソケットAPI
- 現在の標準 - ドメイン名システム
- 階層的な名前解決OSI参照モデル vs TCP/IP
| OSI層 |
TCP/IP層 |
プロトコル例 |
| 7.アプリケーション |
アプリケーション |
HTTP, DNS |
| 6.プレゼンテーション |
TLS |
| 5.セッション |
| 4.トランスポート |
トランスポート |
TCP, UDP |
| 3.ネットワーク |
インターネット |
IP |
| 2.データリンク |
ネットワーク |
Ethernet |
| 1.物理 |
インターフェース |
コンピュータサイエンス的な意味
TCP vs UDP
| 特性 |
TCP |
UDP |
| 接続 |
コネクション型 |
コネクションレス |
| 信頼性 |
順序保証、再送 |
なし |
| オーバーヘッド |
高い |
低い |
| 用途 |
Web、メール |
ゲーム、DNS |
TCPの信頼性メカニズム
送信側: [Data 1] → [Data 2] → [Data 3]
↓ ↓ ↓
受信側: [ACK 1] [ACK 2] [ACK 3]
← ← ←
パケットロス時:
送信側: [Data 2] → (lost) →
タイムアウト
[Data 2] → (再送)
DNSの階層
ルートDNS (.)
/ | \
.com .org .jp
/ \ |
google example co.jp
|
example
実践での活用
ロードバランサー
// 簡易ラウンドロビンLB
struct LoadBalancer {
backends: Vec<SocketAddr>,
current: AtomicUsize,
}
impl LoadBalancer {
fn next_backend(&self) -> SocketAddr {
let idx = self.current.fetch_add(1, Ordering::Relaxed);
self.backends[idx % self.backends.len()]
}
fn forward(&self, client: TcpStream) {
let backend = self.next_backend();
let mut backend_conn = TcpStream::connect(backend)?;
// 双方向にデータを転送
}
}
ネットワーク診断
// TCP接続テスト
fn check_port(addr: &str) -> bool {
TcpStream::connect_timeout(
&addr.parse().unwrap(),
Duration::from_secs(5)
).is_ok()
}
// RTT測定
fn measure_rtt(addr: &str) -> Duration {
let start = Instant::now();
let _ = TcpStream::connect(addr);
start.elapsed()
}
実世界とのギャップ
Nagleアルゴリズム
// 小さなパケットをまとめて送信
// → レイテンシが増加する場合がある
// リアルタイム通信では無効化
socket.set_nodelay(true)?;
MTUとフラグメンテーション
MTU (Maximum Transmission Unit):
- Ethernet: 1500バイト
- PPPoE: 1492バイト
大きなパケットは分割される
→ Path MTU Discovery で最適サイズを検出
NATの問題
プライベートネットワーク → NAT → インターネット
問題:
- サーバーがプライベートIP側からアクセス不可
- P2P通信が困難
解決策:
- UDPホールパンチング
- STUNサーバー
- TURN中継