CFSocketでIPv6マルチキャスト送信
CF系APIを使ってIPv6マルチキャストUDPパケットを送信するサンプルです。 エラー処理等かなりいい加減なのでご注意下さい。 説明文をそのうち書くかも知れませんが、今は面倒なのでコードを解読して下さい。
サンプルコード
このサンプルのポイントは、CFSocketCreate()をPF_INET6で作成しているところと、IPV6_MULTICAST_IFを利用してマルチキャスト送出インターンフェースを指定しているところです。
IPv4のIP_MULTICAST_IFはネットワークインターフェースについているIPv4アドレスを利用して設定を行いますが、IPv6のIPV6_MULTICAST_IFはネットワークインターフェース番号を利用して設定を行うという違いがあるのでご注意下さい。 ネットワークインターフェース番号は、if_nametoindex()を利用して取得できます。
#import <Cocoa/Cocoa.h>
#import <netinet/in.h>
#import <sys/socket.h>
#import <errno.h>
NSAutoreleasePool *pool = NULL;
void
showerror_and_release_pool()
{
NSError *nserr;
nserr = [NSError errorWithDomain:NSPOSIXErrorDomain
code:errno
userInfo:NULL];
NSLog(@"%@", [nserr localizedDescription]);
[pool release];
}
int
main()
{
CFSocketRef sock;
CFSocketError err;
pool = [[NSAutoreleasePool alloc] init];
sock = CFSocketCreate(kCFAllocatorDefault, PF_INET6, SOCK_DGRAM,
IPPROTO_UDP,
kCFSocketNoCallBack,
NULL, NULL);
if (sock == NULL) {
showerror_and_release_pool();
return 1;
}
struct sockaddr_in6 dest;
memset(&dest, 0, sizeof(dest));
dest.sin6_len = sizeof(dest);
dest.sin6_family = AF_INET6;
dest.sin6_port = htons(10000);
inet_pton(AF_INET6, "ff12::1111:cafe", &dest.sin6_addr); /* change here */
unsigned int ifidx = if_nametoindex("en0"); /* change here */
NSLog(@"ifindex = %d", ifidx);
if (setsockopt(CFSocketGetNative(sock),
IPPROTO_IPV6,
IPV6_MULTICAST_IF,
(char *)&ifidx, sizeof(ifidx)) != 0) {
NSLog(@"setsockopt failed");
showerror_and_release_pool();
return 1;
}
CFDataRef destData = CFDataCreate(NULL, (unsigned char *)&dest, sizeof(dest));
CFDataRef msgData = CFDataCreate(NULL, (unsigned char *)"HOGE", 4);
err = CFSocketSendData(sock, destData, msgData, 4);
if (err != kCFSocketSuccess) {
NSLog(@"CFSocketSendData failed");
showerror_and_release_pool();
return 1;
}
[pool release];
return 0;
}