ブロードキャストは IPv6 ではサポートされていません。サポートしているのは IPv4 のみです。
データグラムソケットにより送信されたメッセージは、接続されているネットワークのすべてのホストに届くようブロードキャストを行うことができます。システムのソフトウェア上でのブロードキャストのシミュレーションは行われないため、ネットワークがブロードキャストをサポートしていなければなりません。ブロードキャストはネットワーク上のすべてのホストにサービスを強制するため、ネットワークメッセージはネットワークに大きい負荷をかける場合があります。ブロードキャストは主に 2 つの目的に使用されます。アドレスが不明なローカルネットワーク上の資源の検索、またアクセス可能なすべての隣接ホストへ送られる情報のルーティングを行う場合に使用されます。
ブロードキャストメッセージの送信を行うには、インターネットデータグラムソケットを作成します。
s = socket(AF_INET, SOCK_DGRAM, 0);ソケットのポート番号を割り当てます。
sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(MYPORT); bind(s, (struct sockaddr *) &sin, sizeof sin);
ネットワークのブロードキャストアドレス宛てに送信を行うことにより、データグラムは 1 つのネットワーク上のみでブロードキャストを行うことが可能です。また netinet/in.h 内で定義されている特別なアドレス INADDR_BROADCAST に送信することにより、接続されているすべてのネットワークに対し、データグラムのブロードキャストを行うことが可能です。
システムにはシステム上のネットワークインタフェースに関する情報の数 (IP アドレスおよびブロードキャストアドレスを含む) を判定するメカニズムが装備されています。SIOCGIFCONF ioctl(2) 呼び出しはホストのインタフェース構成を単一 ifconf 構造体において (戻り値として) 返します。この構造体にはホストが接続されている各ネットワークインタフェースによりサポートされる各アドレスファミリに対し個別の ifreq 構造体の配列が含まれます。例 2-18 ではこれらの構造体の net/if.h 内における定義を行っています。
struct ifreq {
#define IFNAMSIZ 16
char ifr_name[IFNAMSIZ]; /* たとえば名前が "en0" */
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
char ifru_oname[IFNAMSIZ]; /* 名前の場合、その他 */
struct sockaddr ifru_broadaddr;
short ifru_flags;
int ifru_metric;
char ifru_data[1]; /* インタフェース依存データ */
char ifru_enaddr[6];
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_oname ifr_ifru.ifru_oname
#define ifr_broadaddr ifr_ifru.ifru_broadaddr
#define ifr_flags ifr_ifru.ifru_flags
#define ifr_metric ifr_ifru.ifru_metric
#define ifr_data ifr_ifru.ifru_data
#define ifr_enaddr ifr_ifru.ifru_enaddr
};
インタフェース構成を取り出す呼び出しは以下の通りです。
/*
* インタフェースの数を検索するため SIOCGIFNUM ioctl を実行。
*
* 発見されたインタフェースの数に相当する空間を割り当て。
*
* 割り当てられたバッファーに対し SIOCGIFCONF を実行。
*
*/
if (ioctl(s, SIOCGIFNUM, (char *)&numifs) == -1) {
numifs = MAXIFS;
}
bufsize = numifs * sizeof(struct ifreq);
reqbuf = (struct ifreq *)malloc(bufsize);
if (reqbuf == NULL) {
fprintf(stderr, "out of memory¥n");
exit(1);
}
ifc.ifc_buf = (caddr_t)&reqbuf[0];
ifc.ifc_len = bufsize;
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) == -1) {
perror("ioctl(SIOCGIFCONF)");
exit(1);
}
...
}
この呼び出しの後、 buf にはホストが接続されている各ネットワークに対して個別の ifreq 構造体の配列が格納されます。これらの構造体の順序付けは、まずインタフェース名で、次にサポートするアドレスファミリによって行われます。 ifc.ifc_len は ifreq 構造体に使用されるバイト数に合わせて設定されます。
各構造体は対応するネットワークの利用可能状況、ポイントツーポイント (point-to-point) またはブロードキャストなどを表示するインタフェースフラグのセットを持ちます。例 2-19 は SIOCGIFFLAGS ioctl(2) が ifreq 構造体により指定されたインタフェースのフラグを返すコードの例です。
struct ifreq *ifr;
ifr = ifc.ifc_req;
for (n = ifc.ifc_len/sizeof (struct ifreq); --n >= 0; ifr++) {
/*
* 別の目的でアドレスファミリ用に使用されているインタフェースを
* 使用しないよう注意する。
*/
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
if (ioctl(s, SIOCGIFFLAGS, (char *) ifr) < 0) {
...
}
if ((ifr->ifr_flags & IFF_UP) == 0 ||
(ifr->ifr_flags & IFF_LOOPBACK) ||
(ifr->ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0)
continue;
}
例 2-20 では SIOCGIFBRDADDR ioctl(2) によってインタフェースのブロードキャストが取得可能であることを表現しています。
if (ioctl(s, SIOCGIFBRDADDR, (char *) ifr) < 0) {
...
}
memcpy((char *) &dst, (char *) &ifr->ifr_broadaddr,
sizeof ifr->ifr_broadaddr);
SIOCGIFBRDADDR ioctl(2) はポイントツーポイントインタフェースのアドレスを取得する目的にも使用できます。
インタフェースブロードキャストアドレスの取得が完了したら、sendto(3SOCKET) を使用してブロードキャストデータグラムの送信を行います。
sendto(s, buf, buflen, 0, (struct sockaddr *)&dst, sizeof dst);
ブロードキャストまたはポイントツーポイントアドレスをサポートするホストが接続されている各インタフェースに対し 1 つの sendto(3SOCKET) を使用します。