msdn:
Application developers use only the ss_family member of the SOCKADDR_STORAGE. The remaining three members ensure the SOCKADDR_STORAGE is padded appropriately to achieve 64-bit alignment. Such alignment enables protocol-specific socket address data structures to access fields within a SOCKADDR_STORAGE structure without alignment problems. With its padding, the SOCKADDR_STORAGE structure is 128 bytes in length.
The first field of the SOCKADDR_STORAGE structure is isomorphic with the sockaddr structure to enable simplified transition from sockaddr to SOCKADDR_STORAGE.
For more information about platform-independent SOCKADDR_STORAGE implementation recommendations, refer to RFC 2553, available at www.ietf.org.
// Function: ServerThread
//
// Description:
// This routine services a single server socket. For TCP this means accept
// a client connection and then recv and send in a loop. When the client
// closes the connection, wait for another client, etc. For UDP, we simply
// sit in a loop and recv a datagram and echo it back to its source. For any
// error, this routine exits.
//
DWORD WINAPI ServerThread(LPVOID lpParam)
{
SOCKET s, // Server socket
sc = INVALID_SOCKET; // Client socket (TCP)
SOCKADDR_STORAGE from;
char Buffer[DEFAULT_BUFFER_LEN],
servstr[NI_MAXSERV],
hoststr[NI_MAXHOST];
int socket_type,
retval,
fromlen,
bytecount;
// Retrieve the socket handle
s = (SOCKET) lpParam;
// Get the socket type back
fromlen = sizeof(socket_type);
retval = getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&socket_type, &fromlen);
if (retval == INVALID_SOCKET)
{
fprintf(stderr, "getsockopt(SO_TYPE) failed: %d\n", WSAGetLastError());
goto cleanup;
}
while (1)
{
fromlen = sizeof(from);
if (socket_type == SOCK_STREAM)
{
if (sc != INVALID_SOCKET)
{
//
// If we have a client connection recv and send until done
//
bytecount = recv(sc, Buffer, DEFAULT_BUFFER_LEN, 0);
if (bytecount == SOCKET_ERROR)
{
fprintf(stderr, "recv failed: %d\n", WSAGetLastError());
goto cleanup;
}
else if (bytecount == 0)
{
// Client connection was closed
retval = shutdown(sc, SD_SEND);
if (retval == SOCKET_ERROR)
{
fprintf(stderr, "shutdown failed: %d\n", WSAGetLastError());
goto cleanup;
}
printf("Accepted connection from host %s and port %s\n",
hoststr, servstr);
}
}
else
{
//
// Receive and send data
//
bytecount = recvfrom(s, Buffer, DEFAULT_BUFFER_LEN, 0, (SOCKADDR *)&from, &fromlen);
if (bytecount == SOCKET_ERROR)
{
//
// We may get WSAECONNRESET errors in response to ICMP port unreachable
// messages so we'll just ignore those
//
if (WSAGetLastError() != WSAECONNRESET)
{
fprintf(stderr, "recvfrom failed; %d\n", WSAGetLastError());
goto cleanup;
}
else
{
continue;
}
}
//
// Display the source of the datagram
//
retval = getnameinfo(
(SOCKADDR *)&from,
fromlen,
hoststr,
NI_MAXHOST,
servstr,
NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV
);
if (retval != 0)
{
fprintf(stderr, "getnameinfo failed: %d\n", retval);
goto cleanup;
}
printf("read %d bytes from host %s and port %s\n",
bytecount, hoststr, servstr);
//
// Echo the datagram back
//
bytecount = sendto(s, Buffer, bytecount, 0, (SOCKADDR *)&from, fromlen);
if (bytecount == SOCKET_ERROR)
{
fprintf(stderr, "sendto failed: %d\n", WSAGetLastError());
goto cleanup;
}
printf("sent %d bytes to host %s and port %s\n",
bytecount, hoststr, servstr);
}
}
cleanup:
// Close the client connection if present
if (sc != INVALID_SOCKET)
{
closesocket(sc);
sc = INVALID_SOCKET;
}