Code:
#include <stdio.h>
#include <stdlib.h>
/* Define the Windows version, so microsoft won't have a heart attack */
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <Ws2tcpip.h>
/* Silence those pesky compiler warnings about unused variables */
#define UNUSED_DATA( data ) ( ( void )data )
typedef union internet_protocol_version
{
struct sockaddr_in6 v6; /* IPv6 */
struct sockaddr_in v4; /* IPv4 */
} internet_protocol_version;
typedef struct internet_data
{
internet_protocol_version protcol_version;
unsigned short family;
int socket;
struct addrinfo hints;
struct addrinfo * server_info;
} internet_data;
WSADATA setup_winsock( );
void init_hints( internet_data * data );
void get_host_info( const char * domain, const char * service, internet_data * data );
int try_connect( internet_data * data );
void connect_to_host( internet_data * data );
void free_winsock( );
WSADATA setup_winsock( )
{
int status = 0;
/*
WSADATA is a structure that contains information about the current
system's networking capabilities. It's uneeded in my case.
*/
WSADATA wsa_data;
/* Let's be futuristic and use version 2.2 of Winsock */
if ( ( status = WSAStartup( MAKEWORD( 2, 2 ), &wsa_data ) ) )
{
fprintf( stderr, "WSAStartup failed, System remark : %s\n", gai_strerror( status ) );
exit( 1 );
}
return wsa_data;
}
void init_hints( internet_data * data )
{
memset( &data->hints, 0, sizeof( struct addrinfo ) ); /* Zero out the hints structure */
data->hints.ai_family = AF_UNSPEC; /* We don't care about IPv4 or IPv6 */
data->hints.ai_socktype = SOCK_STREAM; /* We want TCP stream sockets */
data->hints.ai_flags = AI_PASSIVE; /* Fill in our local IP address */
return;
}
void get_host_info( const char * domain, const char * service, internet_data * data )
{
int status = 0;
if ( ( status = getaddrinfo( domain, service, &data->hints, &data->server_info ) ) )
{
fprintf( stderr, "getaddrinfo failed, System remark : %s\n", gai_strerror( status ) );
free_winsock( );
exit( 2 );
}
return;
}
int try_connect( internet_data * data )
{
if ( data->family == AF_INET ) /* If IPv4... */
{
if ( connect( data->socket, ( struct sockaddr * )&data->protcol_version.v4, sizeof( struct sockaddr ) ) == SOCKET_ERROR )
{
fprintf( stderr, "connect failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
return 0;
}
return 1;
}
else /* If IPv6... */
{
if ( connect( data->socket, ( struct sockaddr * )&data->protcol_version.v6, sizeof( struct sockaddr ) ) == SOCKET_ERROR )
{
fprintf( stderr, "connect failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
return 0;
}
return 1;
}
return 0;
}
void connect_to_host( internet_data * data )
{
struct addrinfo * temp = NULL;
for ( temp = data->server_info; temp; temp = temp->ai_next )
{
if ( temp->ai_family == AF_INET ) /* If IPv4... */
{
data->protcol_version.v4 = *( struct sockaddr_in * )temp;
data->family = AF_INET;
/* Use TCP/IP with streaming sockets and IPV4 */
data->socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( data->socket == INVALID_SOCKET )
{
fprintf( stderr, "socket failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
continue;
}
else
{
if ( try_connect( data ) ) /* If connected... */
return; /* Return to main. */
else /* else, close the socket and continue the loop. */
{
closesocket( data->socket );
continue;
}
}
}
else if ( temp->ai_family == AF_INET6 ) /* If IPv6... */
{
data->protcol_version.v6 = *( struct sockaddr_in6 * )temp;
data->family = AF_INET6;
/* Use TCP/IP with streaming sockets and IPV6 */
data->socket = socket( AF_INET6, SOCK_STREAM, IPPROTO_TCP );
if ( data->socket == INVALID_SOCKET )
{
fprintf( stderr, "socket failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
continue;
}
else
{
if ( try_connect( data ) ) /* If connected... */
return; /* Return to main. */
else /* else, close the socket and continue the loop. */
{
closesocket( data->socket );
continue;
}
}
}
break;
}
fprintf( stderr, "\nCouldn't connect to server!\n" );
freeaddrinfo( data->server_info );
free_winsock( );
exit( 2 );
}
void free_winsock( )
{
/* Let's free whatever resources our Windows OS wanted to use... */
if ( WSACleanup() )
{
fprintf( stderr, "WSACleanup failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
exit( 3 );
}
return;
}
int main( )
{
WSADATA wsa_data = { 0 };
internet_data my_data;
/* Set up */
wsa_data = setup_winsock( );
UNUSED_DATA( wsa_data ); /* Inhibit compiler warnings */
init_hints( &my_data ); /* Setup our preferences */
get_host_info( "www.yahoo.com", "smtp", &my_data ); /* Get information about the host */
connect_to_host( &my_data ); /* Connect to the host with the information we got earlier */
/* Clean up */
closesocket( my_data.socket );
freeaddrinfo( my_data.server_info );
free_winsock( );
return 0;
}
I'm linking with w2_32.dll.