SOCKADDR_STORAGE??????????????????????????????????这是什么类型,我把MSDN查了个遍,也没有看到这种东西 int recvfrom( SOCKET s, char FAR* buf, int len, int flags, struct sockaddr FAR *from, int FAR *fromlen );
// 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; } closesocket(sc); sc = INVALID_SOCKET; } else { printf("read %d bytes\n", bytecount); // // Now echo the data back // bytecount = send(sc, Buffer, bytecount, 0); if (bytecount == SOCKET_ERROR) { fprintf(stderr, "send failed: %d\n", WSAGetLastError()); goto cleanup; } printf("wrote %d bytes\n", bytecount); } } else { // // No client connection so wait for one // sc = accept(s, (SOCKADDR *)&from, &fromlen); if (sc == INVALID_SOCKET) { fprintf(stderr, "accept failed: %d\n", WSAGetLastError()); goto cleanup; } // Display the client's address 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("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; } ExitThread(0); }
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.
int recvfrom(
SOCKET s,
char FAR* buf,
int len,
int flags,
struct sockaddr FAR *from,
int FAR *fromlen
);
buf,
buflen - ((sizeof(SOCKADDR_IN) + 16) * 2),
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&lpLocalSockaddr,
&LocalSockaddrLen,
&lpRemoteSockaddr,
&RemoteSockaddrLen
);后, 怎么得到lpLocalSockaddr, or lpRemoteSockaddr的地址呐?大虾帮忙!!!
//
// 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;
} closesocket(sc);
sc = INVALID_SOCKET;
}
else
{
printf("read %d bytes\n", bytecount); //
// Now echo the data back
// bytecount = send(sc, Buffer, bytecount, 0);
if (bytecount == SOCKET_ERROR)
{
fprintf(stderr, "send failed: %d\n", WSAGetLastError());
goto cleanup;
} printf("wrote %d bytes\n", bytecount);
}
}
else
{
//
// No client connection so wait for one
//
sc = accept(s, (SOCKADDR *)&from, &fromlen);
if (sc == INVALID_SOCKET)
{
fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
goto cleanup;
} // Display the client's address
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("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;
} ExitThread(0);
}
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.