title: What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?
body: <p>I know that sockaddr_in is for IPv4, and sockaddr_in6 for IPv6. The confusion to me is the difference between sockaddr and sockaddr_in[6]. </p>
  
  <p>Some functions accept <code>sockaddr</code> and some functions accept <code>sockaddr_in</code> or <code>sockaddr_in6</code>, so:</p>
  
  <ul>
  <li>what's the rule?  </li>
  <li>And why is there a need for two different structures?</li>
  </ul>
  
  <p>And because the <code>sizeof(sockaddr_in6) &gt; sizeof(sockaddr) == sizeof(sockaddr_in)</code>.</p>
  
  <ul>
  <li>Does that mean we should always use sockaddr_in6 to allocate memory in stack and cast to sockaddr and sockaddr_in if we need to support ipv4 and ipv6?</li>
  </ul>
  
  <p>One example is: we have a socket, and we want to get the string ip address of it (it can be ipv4 or ipv6).</p>
  
  <p>We first call <code>getsockname</code> to get an <code>addr</code> and then call <code>inet_ntop</code> based on the <code>addr.sa_family</code>.</p>
  
  <p>Is there anything wrong with this code snippet?</p>
  
  <pre><code>char ipStr[256];
  sockaddr_in6 addr_inv6;
  sockaddr* addr = (sockaddr*)&amp;addr_inv6;
  sockaddr_in* addr_in = (sockaddr_in*)&amp;addr_inv6;
  
  socklen_t len = sizeof(addr_inv6);
  getsockname(_socket, addr, &amp;len);
  
  if (addr-&gt;sa_family == AF_INET6) {
      inet_ntop(addr_inv6.sin6_family, &amp;addr_inv6.sin6_addr, ipStr, sizeof(ipStr)); 
      // &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;IS THIS LINE VALID, getsockname expected a sockaddr, but we use 
      // it output parameter as sockaddr_in6.
  } else {
      inet_ntop(addr_in-&gt;sin_family, &amp;addr_in-&gt;sin_addr, ipStr, sizeof(ipStr));
  }
  </code></pre>