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

getsockopt

関数
ソケットオプションの値を取得する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

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

INT getsockopt(
    SOCKET s,
    INT level,
    INT optname,
    LPSTR optval,
    INT* optlen
);

パラメーター

名前方向説明
sSOCKETinソケットを識別するディスクリプタ。
levelINTinオプションが定義されているレベル。例: SOL_SOCKET
optnameINTin値を取得する対象のソケットオプション。例: SO_ACCEPTCONNoptname の値は、指定した level 内で定義されているソケットオプションでなければなりません。そうでない場合の動作は未定義です。
optvalLPSTRout要求したオプションの値が返されるバッファへのポインタ。
optlenINT*inoutoptval バッファのサイズ(バイト単位)へのポインタ。

戻り値の型: INT

公式ドキュメント

getsockopt 関数 (winsock.h) は、ソケットオプションを取得します。

戻り値

エラーが発生しなかった場合、 getsockopt はゼロを返します。それ以外の場合は SOCKET_ERROR が返され、 WSAGetLastError を呼び出すことで具体的なエラーコードを取得できます。

エラーコード 意味
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。
WSAENETDOWN
注意 ネットワークサブシステムが失敗しました。
WSAEFAULT
optval または optlen パラメータがユーザーアドレス空間の有効な部分でないか、optlen パラメータが小さすぎます。
WSAEINPROGRESS
ブロッキング Windows Sockets 1.1 の呼び出しが進行中であるか、サービスプロバイダーがコールバック関数をまだ処理中です。
WSAEINVAL
level パラメータが不明または無効です。
WSAENOPROTOOPT
オプションが不明であるか、指定されたプロトコルファミリでサポートされていません。
WSAENOTSOCK
ディスクリプタがソケットではありません。

解説(Remarks)

getsockopt 関数は、任意の種類・任意の状態のソケットに関連付けられたソケットオプションの現在の値を取得し、その結果を optval に格納します。オプションは複数のプロトコルレベルに存在し得ますが、常に最上位のソケットレベルには存在します。オプションは、パケットルーティングや OOB データ転送など、ソケットの動作に影響を与えます。

選択されたオプションに関連付けられた値は、バッファ optval に返されます。optlen が指す整数には、最初にこのバッファのサイズを格納しておく必要があります。戻り時には、返された値のサイズが設定されます。SO_LINGER の場合、これは LINGER 構造体のサイズになります。その他のほとんどのオプションでは、整数のサイズになります。

パラメータで指定したものが直接または間接的に指すメモリ領域の割り当ては、アプリケーションの責任で行います。

オプションが setsockopt で一度も設定されていない場合、 getsockopt はそのオプションの既定値を返します。

getsockopt では以下のオプションがサポートされています。Type 列は、optval が指すデータの型を示します。

ソケットオプションの詳細については、Socket Options を参照してください。

level パラメータが SOL_SOCKET に設定されている場合、optname パラメータに対して次の表の値が有効です。

意味
SO_ACCEPTCONN BOOL ソケットがリッスン中です。
SO_BROADCAST BOOL ソケットがブロードキャストメッセージの送受信用に構成されています。
SO_BSP_STATE CSADDR_INFO ソケットが使用するローカルアドレス、ローカルポート、リモートアドレス、リモートポート、ソケットの種類、プロトコルを返します。
SO_CONDITIONAL_ACCEPT BOOL 現在のソケットの状態を返します。これは以前の setsockopt の呼び出し結果か、システムの既定値のいずれかです。
SO_CONNECT_TIME DWORD ソケットが接続されてからの秒数を返します。このソケットオプションは、コネクション指向プロトコルでのみ有効です。
SO_DEBUG BOOL デバッグが有効です。
SO_DONTLINGER BOOL TRUE の場合、SO_LINGER オプションは無効です。
SO_DONTROUTE BOOL ルーティングが無効です。この設定は AF_INET ソケットでは成功しますが無視されます。AF_INET6 ソケットでは WSAENOPROTOOPT で失敗します。このオプションは ATM ソケットではサポートされていません。
SO_ERROR int エラー状態を取得してクリアします。
SO_EXCLUSIVEADDRUSE BOOL 他のソケットが同じアドレスとポートにバインドされるのを防ぎます。このオプションは bind 関数を呼び出す前に設定する必要があります。
SO_GROUP_ID GROUP 予約済み。
SO_GROUP_PRIORITY int 予約済み。
SO_KEEPALIVE BOOL キープアライブが送信されています。ATM ソケットではサポートされていません。
SO_LINGER LINGER 構造体 現在の linger オプションを返します。
SO_MAX_MSG_SIZE unsigned int メッセージ指向のソケット種別(例: SOCK_DGRAM)におけるメッセージの最大サイズ。ストリーム指向ソケットでは意味を持ちません。
SO_OOBINLINE BOOL OOB データが通常のデータストリーム内で受信されています。(このトピックの説明については Windows Sockets 1.1 Blocking Routines and EINPROGRESS のセクションを参照してください。)
SO_PORT_SCALABILITY BOOL ローカルマシン上の異なるローカルアドレス・ポートのペアに対してワイルドカードポートを複数回割り当てることで、ポート割り当てを最大化し、ソケットのローカルポートスケーラビリティを有効にします。
SO_PROTOCOL_INFO WSAPROTOCOL_INFO このソケットにバインドされているプロトコルのプロトコル情報の記述。
SO_RCVBUF int 受信用に予約されたソケットごとの合計バッファ領域。これは SO_MAX_MSG_SIZE とは無関係であり、必ずしも TCP 受信ウィンドウのサイズに対応するものではありません。
SO_REUSEADDR BOOL 既に使用中のアドレスにソケットをバインドできます。ATM ソケットには適用されません。
SO_SNDBUF int 送信用に予約されたソケットごとの合計バッファ領域。これは SO_MAX_MSG_SIZE とは無関係であり、必ずしも TCP 送信ウィンドウのサイズに対応するものではありません。
SO_TYPE int ソケットの種類(例: SOCK_STREAM)。
PVD_CONFIG サービスプロバイダー依存 ソケット s に関連付けられたサービスプロバイダーからの不透明なデータ構造体オブジェクト。このオブジェクトはサービスプロバイダーの現在の構成情報を格納します。このデータ構造の正確な形式はサービスプロバイダー固有です。

level = IPPROTO_TCP

IPPROTO_TCP socket optionsTCP_NODELAY を参照してください。level = IPPROTO_TCP のソケットオプションに関するより完全で詳細な情報についても、そのトピックを参照してください。

level パラメータが NSPROTO_IPX に設定されている場合、optname パラメータに対して次の表の値が有効です。

注意 Windows NT はすべての IPX オプションをサポートします。Windows Me、Windows 98、Windows 95 は次のオプションのみをサポートします:
IPX_PTYPE
IPX_FILTERPTYPE
IPX_DSTYPE
IPX_RECVHDR
IPX_MAXSIZE
IPX_ADDRESS
意味
IPX_PTYPE int IPX パケットタイプを取得します。
IPX_FILTERPTYPE int 受信フィルタのパケットタイプを取得します。
IPX_DSTYPE int 送信される各パケットの SPX ヘッダー内のデータストリームフィールドの値を取得します。
IPX_EXTENDED_ADDRESS BOOL 拡張アドレッシングが有効かどうかを調べます。
IPX_RECVHDR BOOL すべての受信ヘッダーでプロトコルヘッダーが渡されるかどうかを調べます。
IPX_MAXSIZE int 送信可能な最大データサイズを取得します。
IPX_ADDRESS IPX_ADDRESS_DATA 構造体 IPX がバインドされている特定のアダプターに関する情報を取得します。アダプターの番号付けはゼロ始まりです。adapternum メンバーは戻り時に設定されます。
IPX_GETNETINFO IPX_NETNUM_DATA 構造体 特定の IPX ネットワーク番号に関する情報を取得します。キャッシュに存在しない場合は、RIP を使用して情報を取得します。
IPX_GETNETINFO_NORIP IPX_NETNUM_DATA 構造体 特定の IPX ネットワーク番号に関する情報を取得します。キャッシュに存在しない場合、RIP を使用して情報を取得することはなく、エラーを返します。
IPX_SPXGETCONNECTIONSTATUS IPX_SPXCONNSTATUS_DATA 構造体 接続済みの SPX ソケットに関する情報を取得します。
IPX_ADDRESS_NOTIFY IPX_ADDRESS_DATA 構造体 IPX がバインドされているアダプターに変更が発生したときに、状態通知を取得します。
IPX_MAX_ADAPTER_NUM int 存在するアダプターの最大数を取得します。番号はゼロ始まりです。
IPX_RERIPNETNUMBER IPX_NETNUM_DATA 構造体 IPX_GETNETINFO に似ていますが、ネットワーク情報がローカルキャッシュにある場合でも、IPX に対して名前解決に RIP を強制的に使用させます。
IPX_IMMEDIATESPXACK BOOL SPX 接続が ACK を送信する前に遅延しないように指示します。双方向のトラフィックがないアプリケーションは、パフォーマンスを向上させるためにこれを TRUE に設定する必要があります。
TCP_MAXSEG int TCP の最大セグメントサイズを受け取ります。Windows 10 以降のバージョンでサポートされます。

次の表は、getsockopt 関数でサポートされていない BSD ソケットオプションを表す optname の値を示しています。

意味
SO_RCVLOWAT int 受信の低水位マークを受け取ります。
SO_RCVTIMEO int 受信のタイムアウトを受け取ります。
SO_SNDLOWAT int 送信の低水位マークを受け取ります。
SO_SNDTIMEO int 送信のタイムアウトを受け取ります。
TCP_MAXSEG int TCP の最大セグメントサイズを受け取ります。Windows 10 より前のバージョンではサポートされません。
注意 recv 関数を使用する場合、SO_RCVTIMEO で指定した期間内にデータが到着しないと、 recv 関数は完了します。Windows 2000 より前の Windows バージョンでは、その後に受信されたデータは WSAETIMEDOUT で失敗します。Windows 2000 以降では、SO_RCVTIMEO で指定した期間内にデータが到着しない場合、 recv 関数は WSAETIMEDOUT を返し、データが受信された場合は recv は SUCCESS を返します。

サポートされていないオプションを指定して getsockopt を呼び出すと、 WSAGetLastError からエラーコード WSAENOPROTOOPT が返されます。

getsockopt 関数でサポートされる optname パラメータのソケットオプションの一部について、より詳細な情報を以下に示します。

SO_CONNECT_TIME
このオプションは、ソケットが接続されてからの秒数を返します。このオプションは、コネクション指向プロトコルでのみ有効です。

SO_CONNECT_TIME オプションは、getsockopt 関数とともに使用して、接続が確立されているかどうかを確認できます。このオプションは、ConnectEx 関数の呼び出しが進行中の間にも使用できます。 接続が確立されている場合、SO_CONNECT_TIME オプションでその接続が確立されてからどれくらい経過したかを判断できます。ソケットが接続されていない場合、getsockoptSOCKET_ERROR を返します。このように接続を確認することは、データを送信せずにしばらく確立されたままになっている接続を調べるために必要です。アプリケーションはそのような接続を終了することが推奨されます。

SO_DEBUG
注意 Windows Sockets サービスプロバイダーは、アプリケーションによって SO_DEBUG オプションが設定された場合、デバッグ情報を出力することが推奨されます(ただし必須ではありません)。デバッグ情報を生成するメカニズムやその形式は、このドキュメントの範囲外です。
SO_ERROR
SO_ERROR オプションは、ソケットごとのエラーコードを返してリセットします。これは、 WSAGetLastError および WSASetLastError 関数の呼び出しで処理されるスレッドごとのエラーコードとは異なります。ソケットを使用した呼び出しが成功しても、SO_ERROR オプションが返すソケットベースのエラーコードはリセットされません。
SO_EXCLUSIVEADDRUSE
他のソケットが同じアドレスとポートにバインドされるのを防ぎます。このオプションは bind 関数を呼び出す前に設定する必要があります。詳細については SO_EXCLUSIVEADDRUSE のリファレンスを参照してください。
SO_GROUP_ID
注意 このオプションは予約済みです。また、このオプションは getsockopt 専用であり、値は NULL である必要があります。
SO_GROUP_PRIORITY
このオプションは予約済みです。グループ優先度は、ソケットグループ内の他のソケットに対する指定ソケットの優先度を示します。値は非負の整数で、ゼロが最高優先度に対応します。優先度の値は、不足しがちなリソースをどのように割り当てるべきかについて、下位のサービスプロバイダーへのヒントを表します。たとえば、2 つ以上のソケットがいずれもデータ送信可能な状態になっている場合、最高優先度のソケット(SO_GROUP_PRIORITY の値が最も小さいもの)が最初に処理され、残りはそれぞれの相対優先度に従って順に処理されます。

グループ以外のソケット、またはグループソケットをサポートしないサービスプロバイダーに対しては、WSAENOPROTOOPT エラーコードが示されます。

SO_KEEPALIVE
アプリケーションは、SO_KEEPALIVE ソケットオプションを有効にすることで、TCP/IP サービスプロバイダーに対し、TCP 接続でのキープアライブパケットの使用を有効にするよう要求できます。このオプションは、ソケットのキープアライブオプションの現在の値を照会します。Windows Sockets プロバイダーはキープアライブの使用をサポートする必要はありません。サポートする場合、その正確なセマンティクスは実装固有ですが、IETF の Web サイトで入手できる RFC 1122 の Requirements for Internet Hosts—Communication Layers のセクション 4.2.3.6 に準拠する必要があります。キープアライブの結果として接続が切断された場合、エラーコード WSAENETRESET がそのソケットで進行中のすべての呼び出しに返され、以降の呼び出しはすべて WSAENOTCONN で失敗します。SO_KEEPALIVE は ATM ソケットではサポートされておらず、ATM ソケットでキープアライブパケットの使用を有効にしようとすると、そのソケットからエラーが返されます。
SO_LINGER
SO_LINGER は、ソケットに未送信のデータがキューに入っている状態で closesocket が実行されたときの動作を制御します。SO_LINGER の設定が closesocket のセマンティクスにどのように影響するかについては closesocket を参照してください。アプリケーションは、(optval パラメータが指す) LINGER 構造体を取得することで、現在の動作を得ます。
SO_MAX_MSG_SIZE
これは取得専用のソケットオプションで、特定のサービスプロバイダーが実装する、メッセージ指向のソケット種別(例: SOCK_DGRAM)におけるメッセージの最大送信(送出)サイズを示します。バイトストリーム指向のソケットでは意味を持ちません。最大受信メッセージサイズを取得する手段はありません。
SO_PROTOCOL_INFO
これは取得専用のオプションで、このソケットに関連付けられた WSAPROTOCOL_INFO 構造体を提供します。この構造体の詳細については WSAEnumProtocols を参照してください。
SO_SNDBUF
Windows Sockets の実装が SO_RCVBUF および SO_SNDBUF オプションをサポートしている場合、アプリケーションは異なるバッファサイズ(より大きいか小さいもの)を要求できます。 setsockopt の呼び出しは、実装が要求された量の全体を提供しなかった場合でも成功することがあります。アプリケーションは、実際に提供されたバッファサイズを確認するために、同じオプションを指定してこの関数を呼び出す必要があります。
SO_REUSEADDR
既定では、ソケットは既に使用中のローカルアドレスにバインド(bind を参照)できません。ただし、場合によってはこのようにアドレスを再利用する必要があることもあります。すべての接続はローカルアドレスとリモートアドレスの組み合わせによって一意に識別されるため、リモートアドレスが異なる限り、2 つのソケットが同じローカルアドレスにバインドされていても問題ありません。目的のアドレスが既に別のソケットによって使用されているという理由で bind が拒否されるべきではないことを Windows Sockets プロバイダーに伝えるには、アプリケーションは bind を発行する前に、そのソケットに SO_REUSEADDR ソケットオプションを設定する必要があります。このオプションは bind の時点でのみ解釈される点に注意してください。したがって、既存のアドレスにバインドする予定のないソケットにこのオプションを設定することは不要(ただし無害)であり、 bind の後にオプションを設定またはリセットしても、このソケットや他のソケットには影響しません。SO_REUSEADDR は ATM ソケットには適用されず、アドレスの再利用を要求してもエラーにはなりませんが、ATM ソケットの使用時には効果がありません。
PVD_CONFIG
このオプションは、ソケット s に関連付けられたサービスプロバイダーから不透明なデータ構造体オブジェクトを取得します。このオブジェクトはサービスプロバイダーの現在の構成情報を格納します。このデータ構造の正確な形式はサービスプロバイダー固有です。
TCP_NODELAY
TCP_NODELAY オプションは TCP/IP サービスプロバイダーに固有です。TCP_NODELAY オプションが有効な場合、Nagle アルゴリズムは無効になります(逆も同様)。Nagle アルゴリズム(RFC 896 で説明)は、ホストが送信する小さなパケットの数を削減するのに非常に効果的です。この処理では、未確認のデータが既に送信中である場合に送信データをバッファリングするか、フルサイズのパケットを送信できるようになるまで送信データをバッファリングします。大多数のアプリケーションプロトコルでは Nagle アルゴリズムによって大幅なパフォーマンス向上が得られるため、Windows Sockets の実装では既定で Nagle アルゴリズムを有効にすることが強く推奨されます。ただし、一部のアプリケーションではこのアルゴリズムがパフォーマンスを妨げることがあり、同じオプションを指定した setsockopt を使用して無効にできます。これは、多数の小さなメッセージが送信され、メッセージ間の時間遅延が保たれるアプリケーションです。
注意 getsockopt のようなブロッキング Winsock 呼び出しを発行する際、呼び出しが完了する前に Winsock がネットワークイベントを待機する必要がある場合があります。この状況では Winsock はアラート可能な待機を実行し、同じスレッドでスケジュールされた非同期プロシージャ呼び出し(APC)によって中断されることがあります。同じスレッドで進行中のブロッキング Winsock 呼び出しを中断した APC の内部で別のブロッキング Winsock 呼び出しを発行すると、未定義の動作につながるため、Winsock クライアントは決してこれを試みてはなりません。

サンプルコード

次のコードサンプルは、getsockopt 関数の使用方法を示しています。
#include <stdio.h>
#include "winsock2.h"
#include <windows.h>

void main() {

  //---------------------------------------
  // Declare variables
  WSADATA wsaData;
  SOCKET ListenSocket;
  sockaddr_in service;

  //---------------------------------------
  // Initialize Winsock
  int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
  if( iResult != NO_ERROR )
    printf("Error at WSAStartup\n");

  //---------------------------------------
  // Create a listening socket
  ListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  if (ListenSocket == INVALID_SOCKET) {
    printf("Error at socket()\n");
    WSACleanup();
    return;
  }

  //---------------------------------------
  // Bind the socket to the local IP address
  // and port 27015
  hostent* thisHost;
  char* ip;
  u_short port;
  port = 27015;
  thisHost = gethostbyname("");
  ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);

  service.sin_family = AF_INET;
  service.sin_addr.s_addr = inet_addr(ip);
  service.sin_port = htons(port);
 
  if ( bind( ListenSocket,(SOCKADDR*) &service, sizeof(service) )  == SOCKET_ERROR ) {
    printf("bind failed\n");
    closesocket(ListenSocket);
    return;
  }

  //---------------------------------------
  // Initialize variables and call getsockopt. 
  // The SO_ACCEPTCONN parameter is a socket option 
  // that tells the function to check whether the 
  // socket has been put in listening mode or not. 
  // The various socket options return different
  // information about the socket. This call should
  // return 0 to the optVal parameter, since the socket
  // is not in listening mode.
  int optVal;
  int optLen = sizeof(int);

  if (getsockopt(ListenSocket, 
    SOL_SOCKET, 
    SO_ACCEPTCONN, 
    (char*)&optVal, 
    &optLen) != SOCKET_ERROR)
    printf("SockOpt Value: %ld\n", optVal);

  //---------------------------------------
  // Put the listening socket in listening mode.
  if (listen( ListenSocket, 100 ) == SOCKET_ERROR) {
    printf("error listening\n");
  } 

  //---------------------------------------
  // Call getsockopt again to verify that 
  // the socket is in listening mode.
  if (getsockopt(ListenSocket, 
    SOL_SOCKET, 
    SO_ACCEPTCONN, 
    (char*)&optVal, 
    &optLen) != SOCKET_ERROR)
    printf("SockOpt Value: %ld\n", optVal);

  WSACleanup();
  return;
}

IrDA ソケットに関する注意

IrDA ソケット接続を開始する前に、 getsockopt(,,IRLMP_ENUMDEVICES,,) 関数呼び出しを実行してデバイスアドレスを取得する必要があります。この呼び出しは、利用可能なすべての IrDA デバイスのリストを返します。関数呼び出しから返されたデバイスアドレスは SOCKADDR_IRDA 構造体にコピーされ、それが続く connect 関数呼び出しで使用されます。

ディスカバリは 2 つの方法で実行できます:

  1. 1 つ目は、IRLMP_ENUMDEVICES オプションを指定して getsockopt 関数を呼び出す方法で、これによりアイドル状態の各アダプターで 1 回のディスカバリが実行されます。検出されたデバイスと(アクティブなアダプター上の)キャッシュされたデバイスのリストが直ちに返されます。

    次のコードはこのアプローチを示しています。

    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <af_irda.h>
    #include <stdio.h>
    #include <windows.h>
    
    // link with Ws2_32.lib
    
    int __cdecl main()
    {
    
        //-----------------------------------------
        // Declare and initialize variables
        WSADATA wsaData;
    
        int iResult;
        int i;
        DWORD dwError;
    
        SOCKET Sock = INVALID_SOCKET;
    
    #define DEVICE_LIST_LEN    10
    
    
        SOCKADDR_IRDA DestSockAddr = { AF_IRDA, 0, 0, 0, 0, "SampleIrDAService" };
    
        unsigned char DevListBuff[sizeof (DEVICELIST) -
                                  sizeof (IRDA_DEVICE_INFO) +
                                  (sizeof (IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
    
        int DevListLen = sizeof (DevListBuff);
        PDEVICELIST pDevList;
    
        pDevList = (PDEVICELIST) & DevListBuff;
    
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed: %d\n", iResult);
            return 1;
        }
    
        Sock = socket(AF_IRDA, SOCK_STREAM, 0);
        if (Sock == INVALID_SOCKET) {
            dwError = WSAGetLastError();
            printf
                ("socket failed trying to create an AF_IRDA socket with error %d\n",
                 dwError);
    
            if (dwError == WSAEAFNOSUPPORT) {
                printf("Check that the local computer has an infrared device\n");
                printf
                    ("and a device driver is installed for the infrared device\n");
            }
            WSACleanup();
            return 1;
        }
        // Sock is not in connected state
        iResult = getsockopt(Sock, SOL_IRLMP, IRLMP_ENUMDEVICES,
                             (char *) pDevList, &DevListLen);
        if (iResult == SOCKET_ERROR) {
            printf("getsockopt failed with error %d\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    
        if (pDevList->numDevice == 0) {
            // no devices discovered or cached
            // not a bad idea to run a couple of times
            printf("No IRDA devices were discovered or cached\n");
        } else {
            // one per discovered device
            for (i = 0; i < (int) pDevList->numDevice; i++) {
                // typedef struct _IRDA_DEVICE_INFO
                // {
                //     u_char    irdaDeviceID[4];
                //     char      irdaDeviceName[22];
                //     u_char    irdaDeviceHints1;
                //     u_char    irdaDeviceHints2;
                //     u_char    irdaCharSet;
                // } _IRDA_DEVICE_INFO;
    
                // pDevList->Device[i]. see _IRDA_DEVICE_INFO for fields
                // display the device names and let the user select one
            }
        }
    
        // assume the user selected the first device [0]
        memcpy(&DestSockAddr.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0],
               4);
    
        iResult = connect(Sock, (const struct sockaddr *) &DestSockAddr,
                          sizeof (SOCKADDR_IRDA));
        if (iResult == SOCKET_ERROR) {
            printf("connect failed with error %d\n", WSAGetLastError());
        } else
            printf("connect to first IRDA device was successful\n");
    
        WSACleanup();
        return 0;
    }
    
  2. IrDA デバイスアドレスのディスカバリを実行する 2 つ目のアプローチは、レイジーディスカバリを実行する方法です。このアプローチでは、検出されたデバイスのリストがスタックによる前回のディスカバリ実行から変化するまで、アプリケーションには通知されません。
前の表の Type 列に示されている DEVICELIST 構造体は、デバイス記述の拡張可能な配列です。IrDA は、指定されたバッファに収まる数だけデバイス記述を埋め込みます。デバイス記述は、sockaddr_irda 構造体を形成するために必要なデバイス識別子と、デバイスを説明する表示可能な文字列で構成されます。

前の表の Type 列に示されている IAS_QUERY 構造体は、ピアデバイスの IAS データベースから単一クラスの単一属性を取得するために使用されます。アプリケーションは、照会するデバイスとクラス、および属性と属性の型を指定します。デバイスは事前に getsockopt(IRLMP_ENUMDEVICES) の呼び出しによって取得されている必要があります。アプリケーションは、返されるパラメータ用に必要なサイズのバッファを割り当てることが期待されます。

多くのレベルのソケットオプションは IrDA にとって意味を持ちません。SO_LINGERSO_DONTLINGER のみが明示的にサポートされています。

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>

INT getsockopt(
    SOCKET s,
    INT level,
    INT optname,
    LPSTR optval,
    INT* optlen
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int getsockopt(
    UIntPtr s,   // SOCKET
    int level,   // INT
    int optname,   // INT
    [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder optval,   // LPSTR out
    ref int optlen   // INT* in/out
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function getsockopt(
    s As UIntPtr,   ' SOCKET
    level As Integer,   ' INT
    optname As Integer,   ' INT
    <MarshalAs(UnmanagedType.LPStr)> optval As System.Text.StringBuilder,   ' LPSTR out
    ByRef optlen As Integer   ' INT* in/out
) As Integer
End Function
' s : SOCKET
' level : INT
' optname : INT
' optval : LPSTR out
' optlen : INT* in/out
Declare PtrSafe Function getsockopt Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal level As Long, _
    ByVal optname As Long, _
    ByVal optval As String, _
    ByRef optlen As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

getsockopt = ctypes.windll.ws2_32.getsockopt
getsockopt.restype = ctypes.c_int
getsockopt.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    ctypes.c_int,  # level : INT
    ctypes.c_int,  # optname : INT
    wintypes.LPSTR,  # optval : LPSTR out
    ctypes.POINTER(ctypes.c_int),  # optlen : INT* in/out
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
getsockopt = Fiddle::Function.new(
  lib['getsockopt'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    Fiddle::TYPE_INT,  # level : INT
    Fiddle::TYPE_INT,  # optname : INT
    Fiddle::TYPE_VOIDP,  # optval : LPSTR out
    Fiddle::TYPE_VOIDP,  # optlen : INT* in/out
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn getsockopt(
        s: usize,  // SOCKET
        level: i32,  // INT
        optname: i32,  // INT
        optval: *mut u8,  // LPSTR out
        optlen: *mut i32  // INT* in/out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int getsockopt(UIntPtr s, int level, int optname, [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder optval, ref int optlen);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_getsockopt' -Namespace Win32 -PassThru
# $api::getsockopt(s, level, optname, optval, optlen)
#uselib "WS2_32.dll"
#func global getsockopt "getsockopt" sptr, sptr, sptr, sptr, sptr
; getsockopt s, level, optname, varptr(optval), varptr(optlen)   ; 戻り値は stat
; s : SOCKET -> "sptr"
; level : INT -> "sptr"
; optname : INT -> "sptr"
; optval : LPSTR out -> "sptr"
; optlen : INT* in/out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global getsockopt "getsockopt" sptr, int, int, var, var
; res = getsockopt(s, level, optname, optval, optlen)
; s : SOCKET -> "sptr"
; level : INT -> "int"
; optname : INT -> "int"
; optval : LPSTR out -> "var"
; optlen : INT* in/out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT getsockopt(SOCKET s, INT level, INT optname, LPSTR optval, INT* optlen)
#uselib "WS2_32.dll"
#cfunc global getsockopt "getsockopt" intptr, int, int, var, var
; res = getsockopt(s, level, optname, optval, optlen)
; s : SOCKET -> "intptr"
; level : INT -> "int"
; optname : INT -> "int"
; optval : LPSTR out -> "var"
; optlen : INT* in/out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procgetsockopt = ws2_32.NewProc("getsockopt")
)

// s (SOCKET), level (INT), optname (INT), optval (LPSTR out), optlen (INT* in/out)
r1, _, err := procgetsockopt.Call(
	uintptr(s),
	uintptr(level),
	uintptr(optname),
	uintptr(optval),
	uintptr(optlen),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function getsockopt(
  s: NativeUInt;   // SOCKET
  level: Integer;   // INT
  optname: Integer;   // INT
  optval: PAnsiChar;   // LPSTR out
  optlen: Pointer   // INT* in/out
): Integer; stdcall;
  external 'WS2_32.dll' name 'getsockopt';
result := DllCall("WS2_32\getsockopt"
    , "UPtr", s   ; SOCKET
    , "Int", level   ; INT
    , "Int", optname   ; INT
    , "Ptr", optval   ; LPSTR out
    , "Ptr", optlen   ; INT* in/out
    , "Int")   ; return: INT
●getsockopt(s, level, optname, optval, optlen) = DLL("WS2_32.dll", "int getsockopt(int, int, int, char*, void*)")
# 呼び出し: getsockopt(s, level, optname, optval, optlen)
# s : SOCKET -> "int"
# level : INT -> "int"
# optname : INT -> "int"
# optval : LPSTR out -> "char*"
# optlen : INT* in/out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn getsockopt(
    s: usize, // SOCKET
    level: i32, // INT
    optname: i32, // INT
    optval: [*c]u8, // LPSTR out
    optlen: [*c]i32 // INT* in/out
) callconv(std.os.windows.WINAPI) i32;
proc getsockopt(
    s: uint,  # SOCKET
    level: int32,  # INT
    optname: int32,  # INT
    optval: ptr char,  # LPSTR out
    optlen: ptr int32  # INT* in/out
): int32 {.importc: "getsockopt", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int getsockopt(
    size_t s,   // SOCKET
    int level,   // INT
    int optname,   // INT
    char* optval,   // LPSTR out
    int* optlen   // INT* in/out
);
ccall((:getsockopt, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, Int32, Int32, Ptr{UInt8}, Ptr{Int32}),
      s, level, optname, optval, optlen)
# s : SOCKET -> Csize_t
# level : INT -> Int32
# optname : INT -> Int32
# optval : LPSTR out -> Ptr{UInt8}
# optlen : INT* in/out -> Ptr{Int32}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t getsockopt(
    uintptr_t s,
    int32_t level,
    int32_t optname,
    char* optval,
    int32_t* optlen);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.getsockopt(s, level, optname, optval, optlen)
-- s : SOCKET
-- level : INT
-- optname : INT
-- optval : LPSTR out
-- optlen : INT* in/out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const getsockopt = lib.func('__stdcall', 'getsockopt', 'int32_t', ['uintptr_t', 'int32_t', 'int32_t', 'char *', 'int32_t *']);
// getsockopt(s, level, optname, optval, optlen)
// s : SOCKET -> 'uintptr_t'
// level : INT -> 'int32_t'
// optname : INT -> 'int32_t'
// optval : LPSTR out -> 'char *'
// optlen : INT* in/out -> 'int32_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  getsockopt: { parameters: ["usize", "i32", "i32", "buffer", "pointer"], result: "i32" },
});
// lib.symbols.getsockopt(s, level, optname, optval, optlen)
// s : SOCKET -> "usize"
// level : INT -> "i32"
// optname : INT -> "i32"
// optval : LPSTR out -> "buffer"
// optlen : INT* in/out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t getsockopt(
    size_t s,
    int32_t level,
    int32_t optname,
    char* optval,
    int32_t* optlen);
C, "WS2_32.dll");
// $ffi->getsockopt(s, level, optname, optval, optlen);
// s : SOCKET
// level : INT
// optname : INT
// optval : LPSTR out
// optlen : INT* in/out
// 構造体/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);
    int getsockopt(
        long s,   // SOCKET
        int level,   // INT
        int optname,   // INT
        byte[] optval,   // LPSTR out
        IntByReference optlen   // INT* in/out
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun getsockopt = getsockopt(
    s : LibC::SizeT,   # SOCKET
    level : Int32,   # INT
    optname : Int32,   # INT
    optval : UInt8*,   # LPSTR out
    optlen : Int32*   # INT* in/out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef getsockoptNative = Int32 Function(UintPtr, Int32, Int32, Pointer<Utf8>, Pointer<Int32>);
typedef getsockoptDart = int Function(int, int, int, Pointer<Utf8>, Pointer<Int32>);
final getsockopt = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<getsockoptNative, getsockoptDart>('getsockopt');
// s : SOCKET -> UintPtr
// level : INT -> Int32
// optname : INT -> Int32
// optval : LPSTR out -> Pointer<Utf8>
// optlen : INT* in/out -> Pointer<Int32>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function getsockopt(
  s: NativeUInt;   // SOCKET
  level: Integer;   // INT
  optname: Integer;   // INT
  optval: PAnsiChar;   // LPSTR out
  optlen: Pointer   // INT* in/out
): Integer; stdcall;
  external 'WS2_32.dll' name 'getsockopt';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "getsockopt"
  c_getsockopt :: CUIntPtr -> Int32 -> Int32 -> CString -> Ptr Int32 -> IO Int32
-- s : SOCKET -> CUIntPtr
-- level : INT -> Int32
-- optname : INT -> Int32
-- optval : LPSTR out -> CString
-- optlen : INT* in/out -> Ptr Int32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getsockopt =
  foreign "getsockopt"
    (size_t @-> int32_t @-> int32_t @-> string @-> (ptr int32_t) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* level : INT -> int32_t *)
(* optname : INT -> int32_t *)
(* optval : LPSTR out -> string *)
(* optlen : INT* in/out -> (ptr int32_t) *)
(* 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 ("getsockopt" getsockopt :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (level :int32)   ; INT
  (optname :int32)   ; INT
  (optval :pointer)   ; LPSTR out
  (optlen :pointer))   ; INT* in/out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $getsockopt = Win32::API::More->new('WS2_32',
    'int getsockopt(WPARAM s, int level, int optname, LPSTR optval, LPVOID optlen)');
# my $ret = $getsockopt->Call($s, $level, $optname, $optval, $optlen);
# s : SOCKET -> WPARAM
# level : INT -> int
# optname : INT -> int
# optval : LPSTR out -> LPSTR
# optlen : INT* in/out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目