Win32 API 日本語リファレンス
ホームNetworking.WinSock › gethostbyname

gethostbyname

関数
ホスト名から対応するホスト情報を取得する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll
#include <windows.h>

HOSTENT* gethostbyname(
    LPCSTR name
);

パラメーター

名前方向説明
nameLPCSTRin検索対象のホスト名を示すANSI文字列。

戻り値の型: HOSTENT*

公式ドキュメント

gethostbyname マクロ関数 (wsipv6ok.h) は、ホスト名に対応するホスト情報をホストデータベースから取得します。

解説(Remarks)

gethostbyname 関数は、Windows Sockets によって割り当てられた構造体である hostent 構造体へのポインターを返します。 hostent 構造体には、name パラメーターで指定したホストの検索が成功した結果が格納されます。

name パラメーターで指定したホストが IPv4 アドレスと IPv6 アドレスの両方を持つ場合、IPv4 アドレスのみが返されます。gethostbyname 関数は name パラメーターに対して IPv4 アドレスのみを返すことができます。ホストの IPv6 アドレスが必要な場合、またはホストの IPv4 アドレスと IPv6 アドレスの両方が必要な場合は、getaddrinfo 関数および関連する addrinfo 構造体を使用してください。

name パラメーターが空の文字列を指している場合、または nameNULL の場合、返される文字列は gethostname 関数の呼び出しが成功したときに返される文字列 (ローカルコンピューターの標準ホスト名) と同じです。

name パラメーターに正当な IPv4 アドレスの文字列表現が含まれている場合、その文字列が表すバイナリ IPv4 アドレスが hostent 構造体で返されます。hostent 構造体の h_name メンバーには IPv4 アドレスの文字列表現が格納され、h_addr_list にはバイナリ IPv4 アドレスが格納されます。name パラメーターに IPv6 アドレスの文字列表現または不正な IPv4 アドレスが含まれている場合、gethostbyname 関数は失敗し、WSANO_DATA を返します。

gethostbyname 関数によって返される hostent 構造体のメモリは、Winsock DLL によってスレッドローカルストレージから内部的に割り当てられます。スレッド上で gethostbyaddr 関数または gethostbyname 関数が何回呼び出されても、割り当てられて使用される hostent 構造体は 1 つだけです。同じスレッド上で gethostbyname または gethostbyaddr 関数をさらに呼び出す場合は、返された hostent 構造体をアプリケーションのバッファーにコピーする必要があります。そうしない場合、戻り値は同じスレッド上で後続の gethostbyname または gethostbyaddr 呼び出しによって上書きされます。返された hostent 構造体に内部的に割り当てられたメモリは、スレッドが終了するときに Winsock DLL によって解放されます。

アプリケーションは、返された hostent 構造体が使用するメモリを解放しようとしてはいけません。アプリケーションがこの構造体を変更したり、そのコンポーネントを解放したりすることは決して許されません。さらに、この構造体はスレッドごとに 1 つのコピーのみが割り当てられるため、アプリケーションは gethostbyname または gethostbyaddr への他の関数呼び出しを発行する前に、必要な情報をコピーしておく必要があります。

gethostbyname 関数は、name に渡された IP アドレス文字列をパラメーターとして受け取り、それをホスト名に解決することはできません。そのような要求は、IPv4 アドレスの文字列表現または不明なホスト名が渡された場合とまったく同じように扱われます。アプリケーションは inet_addr を使用して IPv4 アドレス文字列をバイナリ IPv4 アドレスに変換し、その後別の関数 gethostbyaddr を使用して IPv4 アドレスをホスト名に解決できます。

注意 gethostbyname 関数は、バッファーを渡す前に name パラメーターのサイズをチェックしません。name パラメーターのサイズが不適切な場合、ヒープの破損が発生する可能性があります。

サンプルコード

次の例は、gethostbyname 関数の使用方法を示しています。
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    DWORD dwError;
    int i = 0;

    struct hostent *remoteHost;
    char *host_name;
    struct in_addr addr;

    char **pAlias;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s hostname\n", argv[0]);
        printf("  to return the IP addresses for the host\n");
        printf("       %s www.contoso.com\n", argv[0]);
        printf(" or\n");
        printf("       %s IPv4string\n", argv[0]);
        printf("  to return an IPv4 binary address for an IPv4string\n");
        printf("       %s 127.0.0.1\n", argv[0]);
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    host_name = argv[1];

    printf("Calling gethostbyname with %s\n", host_name);
    remoteHost = gethostbyname(host_name);
    
    if (remoteHost == NULL) {
        dwError = WSAGetLastError();
        if (dwError != 0) {
            if (dwError == WSAHOST_NOT_FOUND) {
                printf("Host not found\n");
                return 1;
            } else if (dwError == WSANO_DATA) {
                printf("No data record found\n");
                return 1;
            } else {
                printf("Function failed with error: %ld\n", dwError);
                return 1;
            }
        }
    } else {
        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);
        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
            printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
        }
        printf("\tAddress type: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf("AF_INET\n");
            break;
        case AF_NETBIOS:
            printf("AF_NETBIOS\n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }
        printf("\tAddress length: %d\n", remoteHost->h_length);

        i = 0;
        if (remoteHost->h_addrtype == AF_INET)
        {
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
                printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr));
            }
        }
        else if (remoteHost->h_addrtype == AF_NETBIOS)
        {   
            printf("NETBIOS address was returned\n");
        }   
    }

    return 0;
}

Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされています。

Windows 8.1 および Windows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストアアプリでサポートされています。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// WS2_32.dll
#include <windows.h>

HOSTENT* gethostbyname(
    LPCSTR name
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr gethostbyname(
    [MarshalAs(UnmanagedType.LPStr)] string name   // LPCSTR
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function gethostbyname(
    <MarshalAs(UnmanagedType.LPStr)> name As String   ' LPCSTR
) As IntPtr
End Function
' name : LPCSTR
Declare PtrSafe Function gethostbyname Lib "ws2_32" ( _
    ByVal name As String) As LongPtr
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

gethostbyname = ctypes.windll.ws2_32.gethostbyname
gethostbyname.restype = ctypes.c_void_p
gethostbyname.argtypes = [
    wintypes.LPCSTR,  # name : LPCSTR
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
gethostbyname = Fiddle::Function.new(
  lib['gethostbyname'],
  [
    Fiddle::TYPE_VOIDP,  # name : LPCSTR
  ],
  Fiddle::TYPE_VOIDP)
#[link(name = "ws2_32")]
extern "system" {
    fn gethostbyname(
        name: *const u8  // LPCSTR
    ) -> *mut HOSTENT;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern IntPtr gethostbyname([MarshalAs(UnmanagedType.LPStr)] string name);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_gethostbyname' -Namespace Win32 -PassThru
# $api::gethostbyname(name)
#uselib "WS2_32.dll"
#func global gethostbyname "gethostbyname" sptr
; gethostbyname name   ; 戻り値は stat
; name : LPCSTR -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "WS2_32.dll"
#cfunc global gethostbyname "gethostbyname" str
; res = gethostbyname(name)
; name : LPCSTR -> "str"
; HOSTENT* gethostbyname(LPCSTR name)
#uselib "WS2_32.dll"
#cfunc global gethostbyname "gethostbyname" str
; res = gethostbyname(name)
; name : LPCSTR -> "str"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procgethostbyname = ws2_32.NewProc("gethostbyname")
)

// name (LPCSTR)
r1, _, err := procgethostbyname.Call(
	uintptr(unsafe.Pointer(windows.BytePtrFromString(name))),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // HOSTENT*
function gethostbyname(
  name: PAnsiChar   // LPCSTR
): Pointer; stdcall;
  external 'WS2_32.dll' name 'gethostbyname';
result := DllCall("WS2_32\gethostbyname"
    , "AStr", name   ; LPCSTR
    , "Ptr")   ; return: HOSTENT*
●gethostbyname(name) = DLL("WS2_32.dll", "void* gethostbyname(char*)")
# 呼び出し: gethostbyname(name)
# name : LPCSTR -> "char*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn gethostbyname(
    name: [*c]const u8 // LPCSTR
) callconv(std.os.windows.WINAPI) [*c]HOSTENT;
proc gethostbyname(
    name: cstring  # LPCSTR
): ptr HOSTENT {.importc: "gethostbyname", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
HOSTENT* gethostbyname(
    const(char)* name   // LPCSTR
);
ccall((:gethostbyname, "WS2_32.dll"), stdcall, Ptr{HOSTENT},
      (Cstring,),
      name)
# name : LPCSTR -> Cstring
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
void* gethostbyname(
    const char* name);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.gethostbyname(name)
-- name : LPCSTR
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const gethostbyname = lib.func('__stdcall', 'gethostbyname', 'void *', ['str']);
// gethostbyname(name)
// name : LPCSTR -> 'str'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  gethostbyname: { parameters: ["buffer"], result: "pointer" },
});
// lib.symbols.gethostbyname(name)
// name : LPCSTR -> "buffer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
void* gethostbyname(
    const char* name);
C, "WS2_32.dll");
// $ffi->gethostbyname(name);
// name : LPCSTR
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Ws2_32 extends StdCallLibrary {
    Ws2_32 INSTANCE = Native.load("ws2_32", Ws2_32.class);
    Pointer gethostbyname(
        String name   // LPCSTR
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun gethostbyname = gethostbyname(
    name : UInt8*   # LPCSTR
  ) : HOSTENT*
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef gethostbynameNative = Pointer<Void> Function(Pointer<Utf8>);
typedef gethostbynameDart = Pointer<Void> Function(Pointer<Utf8>);
final gethostbyname = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<gethostbynameNative, gethostbynameDart>('gethostbyname');
// name : LPCSTR -> Pointer<Utf8>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function gethostbyname(
  name: PAnsiChar   // LPCSTR
): Pointer; stdcall;
  external 'WS2_32.dll' name 'gethostbyname';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "gethostbyname"
  c_gethostbyname :: CString -> IO (Ptr ())
-- name : LPCSTR -> CString
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let gethostbyname =
  foreign "gethostbyname"
    (string @-> returning (ptr void))
(* name : LPCSTR -> string *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library ws2_32 (t "WS2_32.dll"))
(cffi:use-foreign-library ws2_32)

(cffi:defcfun ("gethostbyname" gethostbyname :convention :stdcall) :pointer
  (name :string))   ; LPCSTR
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $gethostbyname = Win32::API::More->new('WS2_32',
    'LPVOID gethostbyname(LPCSTR name)');
# my $ret = $gethostbyname->Call($name);
# name : LPCSTR -> LPCSTR
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型