Go言語でネットワークプログラミングを学ぶ - 第2章

2.1 プロジェクト構造 go-network-programming/ ├── go.mod ├── go.sum ├── main.go ├── packet.go ├── node.go ├── link.go ├── network_stats.go # 新規追加 └── bandwidth_limiter.go # 新規追加 この章では、ネットワークに時間の概念を本格的に導入します。実際のネットワークのように、帯域幅制限、パケット処理時間、スループット測定を実装し、大きなファイルの送信をシミュレートします。 2.2 ネットワーク統計の追加 ネットワークの性能を測定するための統計機能を追加します。 ファイル名: ./network_stats.go package main import ( "fmt" "sync" "time" ) // NetworkStats はネットワークの統計情報を管理する // 実際のネットワークモニタリングツールのような機能を提供 type NetworkStats struct { mu sync.RWMutex startTime time.Time totalPacketsSent int64 totalPacketsRecv int64 totalBytesSent int64 totalBytesRecv int64 packetLossCount int64 lastUpdateTime time.Time } // NewNetworkStats は新しい統計オブジェクトを作成 func NewNetworkStats() *NetworkStats { return &NetworkStats{ startTime: time.Now(), lastUpdateTime: time.Now(), } } // RecordSentPacket は送信パケットを記録 func (ns *NetworkStats) RecordSentPacket(packet *Packet) { ns.mu.Lock() defer ns.mu.Unlock() ns.totalPacketsSent++ ns.totalBytesSent += int64(packet.Size) ns.lastUpdateTime = time.Now() } // RecordReceivedPacket は受信パケットを記録 func (ns *NetworkStats) RecordReceivedPacket(packet *Packet) { ns.mu.Lock() defer ns.mu.Unlock() ns.totalPacketsRecv++ ns.totalBytesRecv += int64(packet.Size) ns.lastUpdateTime = time.Now() } // RecordPacketLoss はパケット損失を記録 func (ns *NetworkStats) RecordPacketLoss() { ns.mu.Lock() defer ns.mu.Unlock() ns.packetLossCount++ ns.lastUpdateTime = time.Now() } // GetThroughput は現在のスループットを計算(bps: bits per second) func (ns *NetworkStats) GetThroughput() float64 { ns.mu.RLock() defer ns.mu.RUnlock() duration := time.Since(ns.startTime).Seconds() if duration == 0 { return 0 } // バイト数をビット数に変換(1バイト = 8ビット) totalBits := float64(ns.totalBytesSent) * 8 return totalBits / duration } // GetPacketLossRate はパケット損失率を計算(0.0-1.0) func (ns *NetworkStats) GetPacketLossRate() float64 { ns.mu.RLock() defer ns.mu.RUnlock() if ns.totalPacketsSent == 0 { return 0.0 } return float64(ns.packetLossCount) / float64(ns.totalPacketsSent) } // Print は統計情報を表示 func (ns *NetworkStats) Print() { ns.mu.RLock() defer ns.mu.RUnlock() duration := time.Since(ns.startTime) throughputBps := ns.GetThroughput() throughputKbps := throughputBps / 1000 lossRate := ns.GetPacketLossRate() * 100 fmt.Printf("=== Network Statistics ===\n") fmt.Printf("Duration: %v\n", duration.Round(time.Millisecond)) fmt.Printf("Packets Sent: %d\n", ns.totalPacketsSent) fmt.Printf("Packets Received: %d\n", ns.totalPacketsRecv) fmt.Printf("Bytes Sent: %d\n", ns.totalBytesSent) fmt.Printf("Bytes Received: %d\n", ns.totalBytesRecv) fmt.Printf("Throughput: %.2f Kbps\n", throughputKbps) fmt.Printf("Packet Loss Rate: %.2f%%\n", lossRate) fmt.Printf("=========================\n") } 2.3 帯域幅制限機能の実装 実際のネットワークのように、帯域幅制限を実装します。 ...

January 11, 2026 · 7 min