Thread: Web-Client program using TCP/IP streaming sockets ( winsock )

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    Web-Client program using TCP/IP streaming sockets ( winsock )

    Hello, I finally got around to trying to complete my objective in networking I mentioned so long ago. I'm having a spot of trouble connecting to the web-server right now though.

    The error message I'm getting is from the connect() function :

    Code:
    connect failed with : 10047,
    System Remark : An address incompatible with the requested protocol was used.
    I looked it up, and I found that it had to do with not choosing the correct protocol format. I looked over my code a lot, and I didn't see how I wasn't using the correct protocol. I formatted it for IPv4 and IPv6 correctly didn't I? I'm not sure what I need to change to get it to work.

    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.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    MSDN says this about AI_PASSIVE.

  3. #3
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288
    Quote Originally Posted by tabstop View Post
    MSDN says this about AI_PASSIVE.
    Huh, I didn't know that it meant I had to bind. I was using Beej's tutorial, I guess that's an area where Unix and Windows aren't the same. Anyways, there were some new problems that have arisen after fixing the AI_PASSIVE problem. I did more research( namely, Complete Winsock Client Code (Windows) ), and used microsoft's sample code to fix some of my function calls.

    Here are the changes I made in the above code I posted :

    I changed my data structure to this :

    Code:
    typedef struct internet_data
    {
        unsigned short family;
        int socket;
    
    
        struct addrinfo hints;
        struct addrinfo * server_info;
    
    
    } internet_data;
    I changed my socket call to this :

    Code:
    data->socket = socket( temp->ai_family, temp->ai_socktype, temp->ai_protocol );
    I changed my try_connect function call to this :

    Code:
    int try_connect( internet_data * data, struct addrinfo * node )
    {
        if ( connect( data->socket, ( struct sockaddr * )node->ai_addr, ( int )node->ai_addrlen ) == SOCKET_ERROR )
        {
            fprintf( stderr, "connect failed with : %d,\nSystem Remark : %s\n", WSAGetLastError( ), gai_strerror( WSAGetLastError( ) ) );
            return 0;
        }
    
    
        printf( "Connected to host!\n" );
        return 1;
    }
    I changed my get_host_info call to this( using http as a control test ) :

    Code:
    get_host_info( "www.yahoo.com", "http", &my_data ); /* Get information about the host */
    Finally, I changed my main call to this :

    Code:
    int main( )
    {
        WSADATA wsa_data = { 0 };
    
    
        internet_data my_data;
    
    
        /* Set up */
        wsa_data = setup_winsock( );
        UNUSED_DATA( wsa_data ); /* Inhibit compiler warnings */
        printf( "Winsock initialized...\n" );
    
    
        init_hints( &my_data ); /* Setup our preferences */
        get_host_info( "www.yahoo.com", "http", &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( );
        printf( "Program exited normally!\n" );
    
    
        return 0;
    }
    Connecting to it using http protocol works without any problems... :

    Code:
    Winsock initialized...
    Connected to host!
    Program exited normally!
    I haven't been able to connect using smtp. I researched and found that most people said yahoo's smtp server is "smtp.mail.yahoo.com", but I tried that and I got error code 10060 ( connection timeout ). There might be a problem since I don't know how to use SSL encryption which is apparently required by yahoo, but I have no idea where the true problem lies. Any help connecting to smtp servers is appreciated.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Difference between Unix sockets and winsock.
    By antex in forum Networking/Device Communication
    Replies: 15
    Last Post: 01-21-2005, 04:53 PM
  2. [C++] FTP client problem (winsock)
    By Niekie in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-19-2003, 09:23 AM
  3. Sockets, Winsock
    By mattbbx in forum Networking/Device Communication
    Replies: 4
    Last Post: 08-21-2003, 04:09 PM
  4. Winsock vs Unix Sockets
    By khoxxxy in forum Networking/Device Communication
    Replies: 4
    Last Post: 08-05-2003, 05:13 AM
  5. winsock ftp client
    By ColdFire in forum Windows Programming
    Replies: 3
    Last Post: 05-07-2003, 03:33 PM