HOSTENT
構造体サイズ=各フィールドのバイト数(x64/x86 で異なる場合は x64/x86 と併記)。x64/x86 列=フィールドのバイトオフセット(HSPで dupptr / lpoke / wpoke 等に使用)。
フィールド
| フィールド | 型 | サイズ | x64 | x86 | 説明 |
|---|---|---|---|---|---|
| h_name | LPSTR | 8/4 | +0 | +0 | ホスト (PC) の正式な名前です。DNS などの名前解決システムを使用している場合は、サーバーが応答を返す原因となった完全修飾ドメイン名 (FQDN) です。ローカルの hosts ファイルを使用している場合は、IPv4 アドレスの後にある最初のエントリです。 |
| h_aliases | CHAR** | 8/4 | +8 | +4 | 別名の NULL 終端配列です。 |
| h_addrtype | SHORT | 2 | +16 | +8 | 返されるアドレスの種類です。 |
| h_length | SHORT | 2 | +18 | +10 | 各アドレスの長さ (バイト単位) です。 |
| h_addr_list | CHAR** | 8/4 | +24 | +12 | ホストのアドレスの NULL 終端リストです。アドレスはネットワークバイトオーダーで返されます。マクロ h_addr は、古いソフトウェアとの互換性のために h_addr_list[0] として定義されています。 |
公式ドキュメント
hostent 構造体は、ホスト名や IPv4 アドレスなど、指定されたホストに関する情報を格納するために関数によって使用されます。アプリケーションは、この構造体を変更したり、その構成要素を解放したりしようとしてはなりません。さらに、 hostent 構造体はスレッドごとに 1 つのコピーしか割り当てられないため、アプリケーションは他の Windows Sockets API を呼び出す前に、必要な情報をコピーしておく必要があります。
解説(Remarks)
gethostbyaddr 関数および gethostbyname 関数は、 hostent 構造体 (Windows Sockets によって割り当てられる構造体) へのポインターを返します。 hostent 構造体には、name パラメーターで指定されたホストの検索に成功した結果が格納されます。
gethostbyaddr 関数および gethostbyname 関数が返す hostent 構造体のメモリーは、Winsock DLL によってスレッドローカルストレージから内部的に割り当てられます。同じスレッドで gethostbyaddr 関数や gethostbyname 関数を何回呼び出しても、割り当てられて使用される hostent 構造体は 1 つだけです。同じスレッドで gethostbyaddr 関数や gethostbyname 関数をさらに呼び出す場合は、返された hostent 構造体をアプリケーションのバッファーにコピーしなければなりません。コピーしないと、戻り値は同じスレッドでの後続の gethostbyaddr 呼び出しや gethostbyname 呼び出しによって上書きされます。返された hostent 構造体のために内部的に割り当てられたメモリーは、スレッドの終了時に Winsock DLL によって解放されます。
アプリケーションは、返された hostent 構造体が使用しているメモリーを解放しようとしてはなりません。アプリケーションは、この構造体を変更したり、その構成要素を解放したりしようとしてはなりません。さらに、この構造体はスレッドごとに 1 つのコピーしか割り当てられないため、アプリケーションは gethostbyaddr や gethostbyname を他に呼び出す前に、必要な情報をコピーしておく必要があります。
例
次の例は、gethostbyname 関数と共に hostent 構造体を使用する方法を示しています。
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#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 ipv4address\n", argv[0]);
printf(" or\n");
printf(" %s hostname\n", argv[0]);
printf(" to return the host\n");
printf(" %s 127.0.0.1\n", argv[0]);
printf(" to return the IP addresses for a host\n");
printf(" %s www.contoso.com\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];
// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if (isalpha(host_name[0])) { /* host address is a name */
printf("Calling gethostbyname with %s\n", host_name);
remoteHost = gethostbyname(host_name);
} else {
printf("Calling gethostbyaddr with %s\n", host_name);
addr.s_addr = inet_addr(host_name);
if (addr.s_addr == INADDR_NONE) {
printf("The IPv4 address entered must be a legal address\n");
return 1;
} else
remoteHost = gethostbyaddr((char *) &addr, 4, AF_INET);
}
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_INET6:
printf("AF_INET6\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);
if (remoteHost->h_addrtype == AF_INET) {
while (remoteHost->h_addr_list[i] != 0) {
addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
printf("\tIPv4 Address #%d: %s\n", i, inet_ntoa(addr));
}
} else if (remoteHost->h_addrtype == AF_INET6)
printf("\tRemotehost is an IPv6 address\n");
}
return 0;
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での定義
#include <windows.h>
// HOSTENT (x64 32 / x86 16 バイト)
typedef struct HOSTENT {
LPSTR h_name;
CHAR** h_aliases;
SHORT h_addrtype;
SHORT h_length;
CHAR** h_addr_list;
} HOSTENT;using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct HOSTENT
{
public IntPtr h_name;
public IntPtr h_aliases;
public short h_addrtype;
public short h_length;
public IntPtr h_addr_list;
}Imports System.Runtime.InteropServices
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure HOSTENT
Public h_name As IntPtr
Public h_aliases As IntPtr
Public h_addrtype As Short
Public h_length As Short
Public h_addr_list As IntPtr
End Structureimport ctypes
from ctypes import wintypes
class HOSTENT(ctypes.Structure):
_fields_ = [
("h_name", ctypes.c_void_p),
("h_aliases", ctypes.c_void_p),
("h_addrtype", ctypes.c_short),
("h_length", ctypes.c_short),
("h_addr_list", ctypes.c_void_p),
]#[repr(C)]
pub struct HOSTENT {
pub h_name: *mut core::ffi::c_void,
pub h_aliases: *mut core::ffi::c_void,
pub h_addrtype: i16,
pub h_length: i16,
pub h_addr_list: *mut core::ffi::c_void,
}import "golang.org/x/sys/windows"
type HOSTENT struct {
h_name uintptr
h_aliases uintptr
h_addrtype int16
h_length int16
h_addr_list uintptr
}type
HOSTENT = record
h_name: Pointer;
h_aliases: Pointer;
h_addrtype: Smallint;
h_length: Smallint;
h_addr_list: Pointer;
end;const HOSTENT = extern struct {
h_name: ?*anyopaque,
h_aliases: ?*anyopaque,
h_addrtype: i16,
h_length: i16,
h_addr_list: ?*anyopaque,
};type
HOSTENT {.bycopy.} = object
h_name: pointer
h_aliases: pointer
h_addrtype: int16
h_length: int16
h_addr_list: pointerstruct HOSTENT
{
void* h_name;
void* h_aliases;
short h_addrtype;
short h_length;
void* h_addr_list;
}HSP用 定義
HSP3.7/3.8 は構造体機能が無いため4byte整数配列(dim)+peek/poke で操作(32/64bitでサイズ・位置が異なる場合はタブで分割)。IronHSP は NSTRUCT(#defstruct/stdim/->)で32/64bit共通。
; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x86 レイアウト)
; HOSTENT サイズ: 16 バイト(x86)
dim st, 4 ; 4byte整数×4(構造体サイズ 16 / 4 切り上げ)
; h_name : LPSTR (+0, 4byte) st.0 = 値 / 値 = st.0 (lpoke/lpeek も可)
; h_aliases : CHAR** (+4, 4byte) st.1 = 値 / 値 = st.1 (lpoke/lpeek も可)
; h_addrtype : SHORT (+8, 2byte) wpoke st,8,値 / 値 = wpeek(st,8)
; h_length : SHORT (+10, 2byte) wpoke st,10,値 / 値 = wpeek(st,10)
; h_addr_list : CHAR** (+12, 4byte) st.3 = 値 / 値 = st.3 (lpoke/lpeek も可)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x64 レイアウト)
; HOSTENT サイズ: 32 バイト(x64)
dim st, 8 ; 4byte整数×8(構造体サイズ 32 / 4 切り上げ)
; h_name : LPSTR (+0, 8byte) qpoke st,0,値 / qpeek(st,0) ※IronHSPのみ。3.7/3.8は lpoke st,0,下位 : lpoke st,4,上位
; h_aliases : CHAR** (+8, 8byte) qpoke st,8,値 / qpeek(st,8) ※IronHSPのみ。3.7/3.8は lpoke st,8,下位 : lpoke st,12,上位
; h_addrtype : SHORT (+16, 2byte) wpoke st,16,値 / 値 = wpeek(st,16)
; h_length : SHORT (+18, 2byte) wpoke st,18,値 / 値 = wpeek(st,18)
; h_addr_list : CHAR** (+24, 8byte) qpoke st,24,値 / qpeek(st,24) ※IronHSPのみ。3.7/3.8は lpoke st,24,下位 : lpoke st,28,上位
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; IronHSP は NSTRUCT(構造体)をサポート。32bit/64bit どちらでも同じコードで動作します。
#defstruct global HOSTENT
#field intptr h_name
#field intptr h_aliases
#field short h_addrtype
#field short h_length
#field intptr h_addr_list
#endstruct
stdim st, HOSTENT ; NSTRUCT 変数を確保
st->h_addrtype = 100
mes "h_addrtype=" + st->h_addrtype