rust-network - 課題

概要

Rustで低レベルネットワークプログラミングを学び、TCPとUDPを使用した通信を実装する課題です。

マンダトリーパート

必須要件

  • TCPエコーサーバー/クライアント
- 受信データをそのまま返す - 複数接続対応

  • UDPチャットシステム
- ブロードキャスト/マルチキャスト - メッセージの送受信

  • 簡易DNSリゾルバー
- DNSクエリの構築 - レスポンスのパース

インターフェース

// TCPエコーサーバー
pub struct TcpEchoServer {
    listener: TcpListener,
}

impl TcpEchoServer {
    pub fn bind(addr: &str) -> io::Result<Self>;
    pub fn run(&self) -> io::Result<()>;
}

// UDPチャット
pub struct UdpChat {
    socket: UdpSocket,
    peers: Vec<SocketAddr>,
}

impl UdpChat {
    pub fn new(port: u16) -> io::Result<Self>;
    pub fn send_message(&self, msg: &str) -> io::Result<()>;
    pub fn receive(&self) -> io::Result<(String, SocketAddr)>;
}

// DNSリゾルバー
pub fn resolve(hostname: &str) -> io::Result<Vec<IpAddr>>;

使用例

// TCPエコーサーバー
let server = TcpEchoServer::bind("0.0.0.0:9000")?;
server.run()?;

// TCPクライアント
let mut stream = TcpStream::connect("127.0.0.1:9000")?;
stream.write_all(b"Hello")?;
let mut buf = [0u8; 1024];
let n = stream.read(&mut buf)?;
assert_eq!(&buf[..n], b"Hello");

// UDPチャット
let chat = UdpChat::new(5000)?;
chat.send_message("Hello, everyone!")?;
let (msg, from) = chat.receive()?;

// DNS解決
let addrs = resolve("example.com")?;
println!("{:?}", addrs);

ボーナスパート

ボーナス1: TCP接続プール

  • 接続の再利用

ボーナス2: タイムアウト処理

  • 読み書きタイムアウト

ボーナス3: NAT穴あけ

  • UDPホールパンチング
  • 提出要件

  • src/tcp.rs - TCP実装
  • src/udp.rs - UDP実装
  • src/dns.rs - DNSリゾルバー
  • Cargo.toml
  • 制限事項

  • tokio, async-std は使用不可
  • 標準ライブラリの std::net のみ使用可能