🐥

[備忘録14]作って学ぶブラウザのしくみ / HTTPを実装する/ ホスト名からIPアドレスへの変換

2025/01/02に公開

DNSを使用してドメイン名からIPアドレスに変換することを名前解決という。特に、ドメイン名からIPアドレスへの変換は正引きと呼ばれ、IPアドレスからドメイン名への変換は逆引きと呼ばれる。

HTTPリクエストではIPアドレスをもとに送り先を特定する。

DNSによる正引きによって、URLに含まれているホストからIPアドレスを知ることができる。ホストやIPアドレスの対応は、DNSサーバによって提供される。Webサイトやnslookupコマンドなどのツールを使うことによってDNSサーバにアクセスし、IPアドレスを知ることができる。
※DNSはRFC1035,1034の仕様に基づいて実装されている。

WasabiOSではIPアドレスを知るためにlookup_hostというAPIを提供している。ブラウザ側の実装では、単にこのAPIを使用するだけでいい。
HttpClient構造体のget関数は以下のようになる

impl HttpClient {
    pub fn get (&self, host: String, port : u16, path: String) -> Result<HttpResponse, Error> {
        let ips = match lookup_host(&host) {
            Ok(ips) => ips,
            Err(e) => {
                return Err(Error::Network(format!("Failed to find IP addresses: {:#?}",e)))
            }
        };

        if ips.len() < 1 {
            return Err(Error::Network("No IP addresses found".to_string()))
        }

    }
}

ソケットアドレスの定義

ソケットアドレスとはTCP/IPネットワーク上で通信する際に、送信元や送信先を認識するために使用されるアドレス。通常IPアドレスとポート番号の組み合わせで表される。例えばブラウザがwebサーバにHTTPリクエストを送信する際に、ソケットアドレスはwebサーバのIPアドレスやHTTPにおける標準ポート番号である80番ポートとなる。

SOcketAddr構造体はnoliライブラリで定義されている。

#[derive(Debug)]
pub struct SocketAddr {
    addr: IpV4Addr,
    port: u16,
}

httpClient構造体のフィールドでSocketAddrの変数を定義する。

httpClient構造体は以下のような実装になる

impl HttpClient {
    pub fn get (&self, host: String, port : u16, path: String) -> Result<HttpResponse, Error> {
        let ips = match lookup_host(&host) {
            Ok(ips) => ips,
            Err(e) => {
                return Err(Error::Network(format!("Failed to find IP addresses: {:#?}",e)))
            }
        };

        if ips.len() < 1 {
            return Err(Error::Network("No IP addresses found".to_string()))
        }
        
        let socket_addr: SocketAddr = (ips[0], port).into();
    }
}

Discussion