アクセスカウンタ - マルチキャストを使用するWinsock 2の実装

マルチキャストは、(また、マルチキャストまたはマルチキャストとして翻訳マルチキャスト)、受信者のグループに情報を送信する送信開始、およびユニキャスト(ユニキャスト)やラジオを通じて、多くの伝送、伝送一つである(放送)に対応しています。
shinobi.jp - アクセス解析, ブログ, カウンター とかを提供しているNINJA TOOLSの別館的サイト
マルチキャストは、それは、IPマルチキャスト(のRFC 1112)のSteve DeeringとホストExtensionsによって定義されている標準のIPネットワーク層プロトコルの拡張がある最も広く使われているIPマルチキャストが基礎を築いた。IPマルチキャスティングのように定義されます:IPデータグラムの"ホストグループ"伝送するために、ホストのグループが識別されるホストの同じセットのゼロまたは複数のIP宛先アドレスで構成されています。。ホストグループのメンバーは動的である、つまり、ホストが参加したり、いつでも残して、ホストグループを。ホストグループは、制限はありません両方の場所でメンバーの数と、ホストが複数のホストグループの両方のメンバになることができます。
Windowsソケットでは1.1マルチキャストので、1.1の実装は、マルチキャストをサポートしていないWindowsソケットの大半が定義されていない。。
表1のWinSock 2マルチキャストのAPI
WSAEnumProtocols()




WSASocket()
タイプを指定します。マルチキャスト
WSAJoinLeaf()
マルチキャストグループに参加して、ロール(送信および/または受信者)を割り当てる
WSAIoctl() SIO_MULTICAST_SCOPE




WSAIoctl() SIO_MULTIPOINT_LOOPBACK
内部ループバック(ループバック)に対する
機能WSAEnumProtocols()を返します契約の詳細な説明に現在インストールされているシステムは、プロトコル情報の構造(WSAPROTOCOL_INFO)の配列を格納されている情報。。
。これらの概念の詳細な説明は、付録BのWinsock 2の仕様を参照してください。IPマルチキャストは、root以外のデータプレーンおよび制御プレーンです。。()は、マルチキャストソケットを要求する機能WSASocketの使用では、これらのロールを指定する必要があります。。これは達成するために4つのフラグをdwFlagsのパラメータを使用して()関数WSASocketによって行われます:
根制御プレーンを使用している場合· WSA_FLAG_MULTIPOINT_C_ROOTは、可能WSAPROTOCOL_INFO命令に対応するエントリだけでは、c_rootノードとしてソケットを作成するために使用。
· WSA_FLAG_MULTIPOINT_C_LEAFは、XP1_SUPPORT_MULTIPOINT WSAPROTOCOL_INFOの方向に対応するエントリのみのみを許可で、c_leafノードとしてソケットを作成するために使用。
根のデータプレーンを使用している場合· WSA_FLAG_MULTIPOINT_D_ROOTは、可能WSAPROTOCOL_INFO命令に対応するエントリだけでは、d_rootノードとしてソケットを作成するために使用。

IPマルチキャストでは、唯一のロゴがWSA_FLAG_MULTIPOINT_C_LEAFとWSA_FLAG_MULTIPOINT_D_LEAF WSASocket()dwFlagsパラメータの関数として使用することができることに注意してください。
。場合、非根データプレーンd_leafソケットが、それは通常、同じソケット上で受信されたかどうかのトラフィック制御を送りたいと願っています。WSAIoctl()関数はSIO_MULTIPOINT_LOOPコマンドコードは、内部ループバックを無効にマルチキャストトラフィックフローまたは有効にするために使用され。
WSAIoctl()関数はSIO_MULTICAST_SCOPEコマンドコードでは、マルチキャストスコープを設定する。マルチキャストを使用する場合は、多くの場合、マルチキャスト通信の範囲を指定する必要があることです。スコープへのルーティングセグメントの定義を含んでいることによって、。。1(デフォルト)から範囲を示しますルータではなく、全体の"ケーブル"への情報発信が。。。
WSAJoinLeaf()関数はマルチセッションにリーフノードを結合するために使用され、関数のプロトタイプを以下に示す:
SOCKET WSAAPI WSAJoinLeaf ( SOCKET s , const struct sockaddr FAR * name , int namelen , LPWSABUF lpCallerData , LPWSABUF lpCalleeData , LPQOS lpSQOS , LPQOS lpGQOS , DWORD dwFlags );
WSAJoinLeafは、()()と同じパラメータと構文、という点を除いては、ソケット記述子((WSAAcceptこの関数は)ありません)とdwFlagsパラメータを返し、一WSAConnectている以上。。この関数では、マルチキャストのみソケットは、入力パラメータとして使用することができるよ。ソケットは、マルチキャスト非ブロッキングモードに設定されている場合、返されたソケット記述子はFD_CONNECT使用することができます対応する命令のみの後に受信される。パラメータ名は、ソケットは、マルチキャストアドレスに参加することを示します。
また、このAPIは、マルチキャストグループから脱退する方法上記に記載されていないした。。
あなたは、Windows 95のプログラム上でIPマルチキャストを開発する場合は、インターネットを通じて無料でダウンロードすることができるのWinSock 2ソフトウェア開発キットWS295SDKをダウンロードする必要がありますWindows 95は、IPマルチキャストをサポートしていません。関連サイトのアドレスは:。。
簡単な例は、Winsock 2の下に与えられたマルチキャストプログラムの設計を示しています。
#include <winsock2.h>
#include <stdio.h>
#define BUFSIZE 1024
#define MAXADDRSTR 16
#define LOOPCOUNT 100
。 */
int CheckWinsockVersion(VOID) {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2、2); / /非同期I / OとのマルチキャストのみをサポートしていますWinSockの2.0またはそれ以降の前に
err = WSAStartup(wVersionRequested, &wsaData);
if (err==0) {
if ((LOBYTE(wsaData.wVersion)==2) && (HIBYTE(wsaData.wVersion)==2))

戻り値は0; / * WinSockのDLLは、許容される、正常な戻りです* /
WSACleanup();
WSAVERNOTSUPPORTED =誤る/ *は、*を返すに失敗したことをサポートしていない/
}
/* Tell the user that we couldn't find a usable WinSock DLL.*/
printf("WinSock DLL does not support requested API version.\n");
return err;
}
int main() {
int nRet, i;
int型nIP_TTL = 1;サブネット内の/ /通信。
BOOL bFlag;
DWORD dFlag, cbRet;
int iLen = MAXADDRSTR;
文字strDestMulti [MAXADDRSTR] ="224.1.1.1"; 224から239から/ /マルチキャストアドレス範囲。
SOCKADDR_IN stSrcAddr, stDestAddr;
SOCKET hSock, hNewSock;
u_short nDestPort = 6666;
WSABUF stWSABuf;
char achInBuf [BUFSIZE];
char achOutBuf[] = "Message number: ";

if (nRet) {
printf ("WSAStartup failed: %d\r\n", nRet);
exit (1);
}
/ソケットアドレスのアドレスに/文字列に変換
nRet = WSAStringToAddress ( strDestMulti, /* address string */
AF_INET, /* address family */
NULL, /* protocol info structure */
(LPSOCKADDR)&stDestAddr, /* socket address string */
&iLen); /* length of socket structure */
if (nRet) {
printf ("WSAStringToAddress(%s) failed, Err: %d\n", strDestMulti, WSAGetLastError());
exit(1);
}
/ /マルチキャストソケットを作成する
hSock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
(LPWSAPROTOCOL_INFO)NULL, 0, WSA_FLAG_OVERLAPPED
| WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF);
if (hSock == INVALID_SOCKET) {
printf ("WSASocket() failed, Err: %d\n", WSAGetLastError());
exit (1);
}

nRet = setsockopt(hSock, /* socket */
SOL_SOCKET, /* socket level */
SO_REUSEADDR, /* socket option */
(char *)&bFlag, /* option value */
sizeof (bFlag)); /* size of value */
if (nRet == SOCKET_ERROR)
printf("setsockopt() SO_REUSEADDR failed, Err: %d\n", WSAGetLastError());
/ /指定されたポートおよび既定のユーザーインターフェイスへのソケットをバインドする
stSrcAddr.sin_family = PF_INET;
stSrcAddr.sin_port = htons (nDestPort);
stSrcAddr.sin_addr.s_addr = INADDR_ANY;
nRet = bind (hSock, (struct sockaddr FAR *)&stSrcAddr, sizeof(struct sockaddr));
if (nRet == SOCKET_ERROR)
printf ("bind failed, Err: %d\n", WSAGetLastError());

nRet = WSAIoctl (hSock, /* socket */
SIO_MULTICAST_SCOPE, /* IP Time-To-Live */
&nIP_TTL, /* input */
sizeof (nIP_TTL), /* size */
NULL, /* output */
0, /* size */
&cbRet, /* bytes returned */
NULL, /* overlapped */
NULL); /* completion routine */
if (nRet)
printf ("WSAIoctl(SIO_MULTICAST_SCOPE) failed, Err: %d\n", WSAGetLastError());
/ /(ループバック)の内部ループバックを許可する。Windows 95は、改革のオプションをサポートしていません
bFlag = TRUE;
nRet = WSAIoctl (hSock, /* socket */
SIO_MULTIPOINT_LOOPBACK, /* LoopBack on or off */
&bFlag, /* input */
sizeof (bFlag), /* size */
NULL, /* output */
0, /* size */
&cbRet, /* bytes returned */
NULL, /* overlapped */
NULL); /* completion routine */
if (nRet)
printf("WSAIoctl(SIO_MULTIPOINT_LOOPBACK) failed, Err: %d\n", WSAGetLastError());
stDestAddr.sin_family = PF_INET;
nRet = WSAHtons( hSock, /* socket */
nDestPort, /* host order value */
&(stDestAddr.sin_port)); /* network order value */
if (nRet == SOCKET_ERROR)
printf("WSAHtons() failed, Err: %d\n", WSAGetLastError());
/ /両方の送信者として指定された特定のマルチキャストグループとの受信に追加
/ / IPマルチキャストでは、返されたソケット記述子のソケット記述子と入力と同じ。
hNewSock = WSAJoinLeaf (hSock, /* socket */
(PSOCKADDR)&stDestAddr, /* multicast address */
sizeof (stDestAddr), /* length of addr struct */
NULL, /* caller data buffer */
NULL, /* callee data buffer */
NULL, /* socket QOS setting */
NULL, /* socket group QOS */
JL_BOTH); /* do both: send *and* receive */
if (hNewSock == INVALID_SOCKET)
printf ("WSAJoinLeaf() failed, Err: %d\n", WSAGetLastError());
/ /ループでは、送信/受信データ。に無限ループ時にテスト
for (i=0;i<LOOPCOUNT;i++) {
static iCounter = 1;
stWSABuf.buf = achOutBuf;
stWSABuf.len = lstrlen(achOutBuf);
cbRet = 0;
itoa(iCounter++, &achOutBuf[16], 10);
nRet = WSASendTo (hSock, /* socket */
&stWSABuf, /* output buffer structure */
1, /* buffer count */
&cbRet, /* number of bytes sent */
0, /* flags */
(struct sockaddr*)&stDestAddr, /* destination address */
sizeof(struct sockaddr), /* size of addr structure */
NULL, /* overlapped structure */
NULL); /* overlapped callback function */
if (nRet == SOCKET_ERROR)
printf("WSASendTo() failed, Err: %d\n", WSAGetLastError());
stWSABuf.buf = achInBuf;
stWSABuf.len = BUFSIZE;
cbRet = 0;
iLen = sizeof (stSrcAddr);
dFlag = 0;
nRet = WSARecvFrom (hSock, /* socket */
&stWSABuf, /* input buffer structure */
1, /* buffer count */
&cbRet, /* number of bytes recv'd */
&dFlag, /* flags */
(struct sockaddr *)&stSrcAddr /* source address */
&iLen, /* size of addr structure */
NULL, /* overlapped structure */
NULL); /* overlapped callback function */
if (nRet == SOCKET_ERROR)
printf("WSARecvFrom() failed, Err:%d\n", WSAGetLastError());
else {
u_short nPort = 0;
文字achAddr [MAXADDRSTR 3] = {0};長さがWindowsのエラー122を返すように小さいです/ /場合
iLen = MAXADDRSTR+3;
nRet = WSAAddressToStringは(/ /アドレスが文字列に変換されます
(struct sockaddr *)&stSrcAddr, /* source address */
sizeof(stSrcAddr), /* size of addr struct */
NULL, /* protocol info */
achAddr, /* address string */
&iLen); /* addr string buf len */
if (nRet == SOCKET_ERROR)
printf("WSAAddressToString() failed, Err: %d\n", WSAGetLastError());
nRet = WSANtohs(hSock, /* socket */
stSrcAddr.sin_port, /* host order value */
&nPort); /* network order value */
if (nRet == SOCKET_ERROR)
printf("WSANtohs() failed, Err: %d\n", WSAGetLastError());
printf ("WSARecvFrom() received %d bytes from %s, port %d :%s\r\n",
cbRet, achAddr[0] ? achAddr : "??", nPort, achInBuf);
}
} /* end for(;;) */
closesocket(hNewSock);
closesocket(hSock);

WSACleanup();
return (0);
} /* end main() */