sockaddr
がからのデータを保持するのに十分な大きさではありません。最初のコード例は、送信元アドレスのデータが満杯にコピーされている、とあなたはbind()
に完全なアドレスを渡しているが、あなたはまた、コピー中にスタックメモリをゴミ箱に移動しているという理由だけで「働きます」。それは割り当て中にアドレスデータを切り捨てているが、それはもうスタックメモリを中傷されていないため、2番目のコード例では動作しません。
sockaddr
はsockaddr_in
のデータを保持するのに十分な大きさなので、どちらのコード例もIPv6では正しく動作しますが、どちらも問題ありません。
:
final_addr
を確保するため
がsockaddr_in
またはのいずれかからのデータを保持するのに十分な大きさである、それはどのsockaddr_...
構造体型からのデータを保持するのに十分な大きさであることが保証され、代わりにsockaddr_storage
として宣言する必要があります
struct sockaddr_storage final_addr;
int size;
if (use IPv6)
{
struct sockaddr_in6 addr6;
// populate addr6 as needed...
memcpy(&final_addr, &addr6, sizeof(addr6));
or
*reinterpret_cast<struct sockaddr_in6*>(&final_addr) = addr6;
size = sizeof(addr6);
}
else
{
struct sockaddr_in addr4;
// populate addr4 as needed...
memcpy(&final_addr, &addr4, sizeof(addr4));
or
*reinterpret_cast<struct sockaddr_in*>(&final_addr) = addr4;
size = sizeof(addr4);
}
bind(fd, reinterpret_cast<struct sockaddr*>(&final_addr), size);
より良いオプションは、あなたに適したsockaddr_...
メモリ・ブロックを作成するためにgetaddrinfo()
または同等品を使用することです:
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
struct addrinfo *addr = NULL;
if (getaddrinfo("ip address here", "port here", &hints, &addr) == 0)
{
bind(fd, addr->ai_addr, addr->ai_addrlen);
freeaddrinfo(addr);
}
あるいは:
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = ...; // SOCK_STREAM, SOCK_DGRAM, etc...
hints.ai_protocol = ...; // IPPROTO_TCP, IPPROTO_UDP, etc...
struct addrinfo *addrs = NULL;
if (getaddrinfo(NULL, "port here", &hints, &addrs) == 0)
{
for (struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
{
int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (fd != -1)
{
bind(fd, addr->ai_addr, addr->ai_addrlen);
// save fd somewhere for later use
...
}
}
freeaddrinfo(addrs);
}
'sockaddr'は' sockaddr_in'(IPv4)の又は 'sockaddr_in6'(IPv6)をバックアップのいずれか不透明ポインタです。 'sin_family'フィールドの他に、これらの構造はまったく異なります。 'reinterpret_cast'と' memcpy() 'はどちらも正しく変換されません。 –
sockaddr_in6にconstキーワードがありますか? – BenPen
私はあなたが誤解していると思います。 Iveは初期化コードの大部分を削除しました。コードはmemcpyを使ってうまく動作します(ソケットは正しくバインドされ、正しく動作します)。しかし、reinterpret_castで失敗します。 – freakish