WSAMSG
構造体サイズ=各フィールドのバイト数(x64/x86 で異なる場合は x64/x86 と併記)。x64/x86 列=フィールドのバイトオフセット(HSPで dupptr / lpoke / wpoke 等に使用)。
フィールド
| フィールド | 型 | サイズ | x64 | x86 | 説明 | ||||
|---|---|---|---|---|---|---|---|---|---|
| name | SOCKADDR* | 8/4 | +0 | +0 | リモートアドレスに関する情報を格納する SOCKET_ADDRESS 構造体へのポインターです。未接続のソケットでのみ使用されます。 | ||||
| namelen | INT | 4 | +8 | +4 | pAddr メンバーが指す SOCKET_ADDRESS 構造体の長さ (バイト単位) です。未接続のソケットでのみ使用されます。 | ||||
| lpBuffers | WSABUF* | 8/4 | +16 | +8 | メッセージデータの受信に使用される WSABUF 構造体の配列です。lpBuffers メンバーは複数のバッファーを保持できるため、スキャッター/ギャザー I/O を使用できます。 | ||||
| dwBufferCount | DWORD | 4 | +24 | +12 | lpBuffers メンバーが指すバッファーの数です。 | ||||
| Control | WSABUF | 16/8 | +32 | +16 | 省略可能な制御データを指定するために使用される WSABUF 型の構造体です。「解説」を参照してください。 | ||||
| dwFlags | DWORD | 4 | +48 | +24 | 1 つ以上の制御フラグで、値の論理 OR として指定します。入力時に dwFlags メンバーに指定できる値は、Winsock2.h ヘッダーファイルで定義されています。出力時に dwFlags メンバーに設定される値は、Ws2def.h ヘッダーファイル (Winsock2.h ヘッダーファイルから自動的にインクルードされます) で定義されています。
|
公式ドキュメント
WSAMSG 構造体は、 LPFN_WSARECVMSG (WSARecvMsg) 関数および WSASendMsg 関数と共に使用され、接続済みおよび未接続のソケットに関するアドレスと省略可能な制御情報、ならびにメッセージデータを格納するためのバッファーの配列を保持します。
解説(Remarks)
Microsoft Windows Software Development Kit (SDK) では、Windows Vista で使用するこの構造体のバージョンは、dwBufferCount メンバーと dwFlags メンバーのデータ型が ULONG として定義されています。アプリケーションをコンパイルする際、ターゲットプラットフォームが Windows Vista 以降 (NTDDI_VERSION >= NTDDI_LONGHORN、_WIN32_WINNT >= 0x0600、または WINVER >= 0x0600) である場合、dwBufferCount メンバーと dwFlags メンバーのデータ型は ULONG になります。
Windows Server 2003 および Windows XP: アプリケーションをコンパイルする際、dwBufferCount メンバーと dwFlags メンバーのデータ型は DWORD になります。
Windows Vista 以降向けにリリースされた Windows SDK では、WSAMSG 構造体は Ws2def.h ヘッダーファイルで定義されています。Ws2def.h ヘッダーファイルは Winsock2.h に自動的にインクルードされるため、直接使用しないでください。
送信中にデータグラムまたは制御データが切り詰められた場合、 WSAMSG 構造体と共に使用している関数は SOCKET_ERROR を返し、 WSAGetLastError 関数の呼び出しは WSAEMSGSIZE を返します。何が切り詰められたのかは、MSG_TRUNC フラグや MSG_CTRUNC フラグを確認してアプリケーションが判断します。
Control メンバーの使用
次の表は、IPv4 および IPv6 で Control メンバーに使用できる制御データのさまざまな用途をまとめたものです。
| プロトコル | cmsg_level | cmsg_type | 説明 |
|---|---|---|---|
| IPv4 | IPPROTO_IP | IP_ORIGINAL_ARRIVAL_IF | データグラムソケットでパケットを受信した元の IPv4 到着インターフェイスを受け取ります。この制御データは、IPv4 の NAT トラバーサルに Teredo、6to4、または ISATAP トンネルが使用される場合にファイアウォールが使用します。WSAMSG 構造体の cmsg_data[] メンバーは ULONG で、Ifdef.h ヘッダーファイルで定義されている IF_INDEX を格納します。 詳細については、IP_ORIGINAL_ARRIVAL_IF ソケットオプションに関する IPPROTO_IP ソケットオプション を参照してください。 Windows Server 2008、Windows Vista、Windows Server 2003 および Windows XP: IP_ORIGINAL_ARRIVAL_IF の cmsg_type はサポートされていません。 |
| IPv4 | IPPROTO_IP | IP_PKTINFO | IPv4 ソケットのパケット情報を指定または受信します。詳細については、IP_PKTINFO ソケットオプションを参照してください。 |
| IPv4 | IPPROTO_IP | IP_ECN | IPv4 ヘッダーの Type of Service (TOS) フィールドの ECN コードポイントを指定または受信します。詳細については、WSASetRecvIPEcn を参照してください。 |
| IPv6 | IPPROTO_IPV6 | IPV6_DSTOPTS | 宛先オプションを指定または受信します。 |
| IPv6 | IPPROTO_IPV6 | IPV6_HOPLIMIT | ホップ制限を指定または受信します。詳細については、IPV6_HOPLIMIT ソケットオプションに関する IPPROTO_IPV6 ソケットオプション を参照してください。 |
| IPv6 | IPPROTO_IPV6 | IPV6_HOPOPTS | ホップバイホップオプションを指定または受信します。 |
| IPv6 | IPPROTO_IPV6 | IPV6_NEXTHOP | ネクストホップアドレスを指定します。 |
| IPv6 | IPPROTO_IPV6 | IPV6_PKTINFO | IPv6 ソケットのパケット情報を指定または受信します。詳細については、IPV6_PKTINFO ソケットオプションを参照してください。 |
| IPv6 | IPPROTO_IPV6 | IPV6_RTHDR | ルーティングヘッダーを指定または受信します。 |
| IPv6 | IPPROTO_IPV6 | IPV6_ECN | IPv6 ヘッダーの Traffic Class フィールドの ECN コードポイントを指定または受信します。詳細については、WSASetRecvIPEcn を参照してください。 |
制御データは 1 つ以上の制御データオブジェクトで構成され、各オブジェクトは次のように定義される WSACMSGHDR 構造体で始まります。
struct wsacmsghdr {
UINT cmsg_len;
INT cmsg_level;
INT cmsg_type;
/* followed by UCHAR cmsg_data[] */
} WSACMSGHDR;
WSACMSGHDR 構造体のメンバーは次のとおりです。
| 用語 | 説明 |
|---|---|
| cmsg_len | WSACMSGHDR の先頭からデータの末尾までのデータのバイト数です (データの後に続く可能性のあるパディングバイトは含みません)。 |
| cmsg_level | 制御情報の発信元となったプロトコルです。 |
| cmsg_type | プロトコル固有の制御情報の種類です。 |
データオブジェクトをたどるには、次のマクロを使用します。
#define LPCMSGHDR *WSA_CMSG_FIRSTHDR(LPWSAMSG msg);
最初の制御データオブジェクトへのポインターを返します。Control メンバーが NULL ポインターである場合など、 WSAMSG 構造体に制御データが存在しない場合は NULL ポインターを返します。
#define LPCMSGHDR *WSA_CMSG_NXTHDR(LPWSAMSG msg, LPWSACMSGHDR cmsg);
次の制御データオブジェクトへのポインターを返します。データオブジェクトがこれ以上存在しない場合は NULL を返します。pcmsg パラメーターが NULL の場合は、最初の制御データオブジェクトへのポインターを返します。
#define UCHAR *WSA_CMSG_DATA(LPWSACMSGHDR pcmsg);
データの先頭バイトへのポインターを返します (構造体では定義されていませんが、cmsg_data メンバーと呼ばれます)。
#define UINT WSA_CMSG_SPACE(UINT length);
データ量を指定すると、制御データオブジェクトの合計サイズを返します。適切なバッファー領域を割り当てるために使用します。アラインメント用のパディングを含みます。
#define UINT WSA_CMSG_LEN(UINT length);
データ量を指定すると、cmsg_len に設定すべき値を返します。アラインメント用のパディングを含みます。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での定義
#include <windows.h>
// WSABUF (x64 16 / x86 8 バイト)
typedef struct WSABUF {
DWORD len;
LPSTR buf;
} WSABUF;
// WSAMSG (x64 56 / x86 28 バイト)
typedef struct WSAMSG {
SOCKADDR* name;
INT namelen;
WSABUF* lpBuffers;
DWORD dwBufferCount;
WSABUF Control;
DWORD dwFlags;
} WSAMSG;using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WSABUF
{
public uint len;
public IntPtr buf;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WSAMSG
{
public IntPtr name;
public int namelen;
public IntPtr lpBuffers;
public uint dwBufferCount;
public WSABUF Control;
public uint dwFlags;
}Imports System.Runtime.InteropServices
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure WSABUF
Public len As UInteger
Public buf As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure WSAMSG
Public name As IntPtr
Public namelen As Integer
Public lpBuffers As IntPtr
Public dwBufferCount As UInteger
Public Control As WSABUF
Public dwFlags As UInteger
End Structureimport ctypes
from ctypes import wintypes
class WSABUF(ctypes.Structure):
_fields_ = [
("len", wintypes.DWORD),
("buf", ctypes.c_void_p),
]
class WSAMSG(ctypes.Structure):
_fields_ = [
("name", ctypes.c_void_p),
("namelen", ctypes.c_int),
("lpBuffers", ctypes.c_void_p),
("dwBufferCount", wintypes.DWORD),
("Control", WSABUF),
("dwFlags", wintypes.DWORD),
]#[repr(C)]
pub struct WSABUF {
pub len: u32,
pub buf: *mut core::ffi::c_void,
}
#[repr(C)]
pub struct WSAMSG {
pub name: *mut core::ffi::c_void,
pub namelen: i32,
pub lpBuffers: *mut core::ffi::c_void,
pub dwBufferCount: u32,
pub Control: WSABUF,
pub dwFlags: u32,
}import "golang.org/x/sys/windows"
type WSABUF struct {
len uint32
buf uintptr
}
type WSAMSG struct {
name uintptr
namelen int32
lpBuffers uintptr
dwBufferCount uint32
Control WSABUF
dwFlags uint32
}type
WSABUF = record
len: DWORD;
buf: Pointer;
end;
WSAMSG = record
name: Pointer;
namelen: Integer;
lpBuffers: Pointer;
dwBufferCount: DWORD;
Control: WSABUF;
dwFlags: DWORD;
end;const WSABUF = extern struct {
len: u32,
buf: ?*anyopaque,
};
const WSAMSG = extern struct {
name: ?*anyopaque,
namelen: i32,
lpBuffers: ?*anyopaque,
dwBufferCount: u32,
Control: WSABUF,
dwFlags: u32,
};type
WSABUF {.bycopy.} = object
len: uint32
buf: pointer
WSAMSG {.bycopy.} = object
name: pointer
namelen: int32
lpBuffers: pointer
dwBufferCount: uint32
Control: WSABUF
dwFlags: uint32struct WSABUF
{
uint len;
void* buf;
}
struct WSAMSG
{
void* name;
int namelen;
void* lpBuffers;
uint dwBufferCount;
WSABUF Control;
uint dwFlags;
}HSP用 定義
HSP3.7/3.8 は構造体機能が無いため4byte整数配列(dim)+peek/poke で操作(32/64bitでサイズ・位置が異なる場合はタブで分割)。IronHSP は NSTRUCT(#defstruct/stdim/->)で32/64bit共通。
; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x86 レイアウト)
; WSAMSG サイズ: 28 バイト(x86)
dim st, 7 ; 4byte整数×7(構造体サイズ 28 / 4 切り上げ)
; name : SOCKADDR* (+0, 4byte) varptr(st)+0 を基点に操作(4byte:入れ子/配列)
; namelen : INT (+4, 4byte) st.1 = 値 / 値 = st.1 (lpoke/lpeek も可)
; lpBuffers : WSABUF* (+8, 4byte) varptr(st)+8 を基点に操作(4byte:入れ子/配列)
; dwBufferCount : DWORD (+12, 4byte) st.3 = 値 / 値 = st.3 (lpoke/lpeek も可)
; Control : WSABUF (+16, 8byte) varptr(st)+16 を基点に操作(8byte:入れ子/配列)
; dwFlags : DWORD (+24, 4byte) st.6 = 値 / 値 = st.6 (lpoke/lpeek も可)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x64 レイアウト)
; WSAMSG サイズ: 56 バイト(x64)
dim st, 14 ; 4byte整数×14(構造体サイズ 56 / 4 切り上げ)
; name : SOCKADDR* (+0, 8byte) varptr(st)+0 を基点に操作(8byte:入れ子/配列)
; namelen : INT (+8, 4byte) st.2 = 値 / 値 = st.2 (lpoke/lpeek も可)
; lpBuffers : WSABUF* (+16, 8byte) varptr(st)+16 を基点に操作(8byte:入れ子/配列)
; dwBufferCount : DWORD (+24, 4byte) st.6 = 値 / 値 = st.6 (lpoke/lpeek も可)
; Control : WSABUF (+32, 16byte) varptr(st)+32 を基点に操作(16byte:入れ子/配列)
; dwFlags : DWORD (+48, 4byte) st.12 = 値 / 値 = st.12 (lpoke/lpeek も可)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; IronHSP は NSTRUCT(構造体)をサポート。32bit/64bit どちらでも同じコードで動作します。
; ※GUID・入れ子構造体はデフォルト型でないため、依存する #defstruct を先に定義(下記に同梱)。
#defstruct global WSABUF
#field int len
#field intptr buf
#endstruct
#defstruct global WSAMSG
#field intptr name
#field int namelen
#field intptr lpBuffers
#field int dwBufferCount
#field WSABUF Control
#field int dwFlags
#endstruct
stdim st, WSAMSG ; NSTRUCT 変数を確保
st->namelen = 100
mes "namelen=" + st->namelen