1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Question about Winsock2 on Windows XP vs Windows 2000

Discussion in 'Software Development' started by tomdkat, Oct 9, 2008.

Thread Status:
Not open for further replies.
  1. tomdkat

    tomdkat Retired Trusted Advisor Thread Starter

    Joined:
    May 6, 2006
    Messages:
    7,148
    We recently started adding IPv6 support to an application I maintain. I'm one of many developers maintaining this application.

    Anyway, we're using the getaddrinfo() function to reslove IP addresses into hostnames and so on. On a PC running Windows 2000, getaddrinfo() behaved differently than on another PC running Windows XP Pro.

    Here is a test case from the getaddrinfo() MSDN page:
    Code:
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    
    // link with Ws2_32.lib
    
    int __cdecl main(int argc, char **argv)
    {
    
        //-----------------------------------------
        // Declare and initialize variables
        WSADATA wsaData;
        int iResult;
    
        DWORD dwRetval;
    
        int i = 1;
        
        char *port = "27015";
    
        struct addrinfo *result = NULL;
        struct addrinfo *ptr = NULL;
        struct addrinfo hints;
    
    
        // Validate the parameters
        if (argc != 2) {
            printf("usage: %s <hostname>\n", argv[0]);
            printf("  getaddrinfo provides protocol-independent translation\n");
            printf(   "   from an ANSI host name to an IP address\n");
            printf("      %s www.contoso.com\n", argv[0]);
            return 1;
        }
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed: %d\n", iResult);
            return 1;
        }
    
        //--------------------------------
        // Setup the hints address info structure
        // which is passed to the getaddrinfo() function
        ZeroMemory( &hints, sizeof(hints) );
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
    	hints.ai_flags = AI_NUMERICHOST |AI_PASSIVE;
    
    
    //--------------------------------
    // Call getaddrinfo(). If the call succeeds,
    // the result variable will hold a linked list
    // of addrinfo structures containing response
    // information
    /*    dwRetval = getaddrinfo(argv[1], port, &hints, &result);*/
    [b]    dwRetval = getaddrinfo(0, port, &hints, &result);[/b]
        if ( dwRetval != 0 ) {
            printf("getaddrinfo failed with error: %d\n", dwRetval);
            WSACleanup();
            return 1;
        }
    
        printf("getaddrinfo returned success\n");
        
        // Retrieve each address and print out the hex bytes
        for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
    
            printf("getaddrinfo response %d\n", i++);
            printf("\tFlags: 0x%x\n", ptr->ai_flags);
            printf("\tFamily: ");
            switch (ptr->ai_family) {
                case AF_UNSPEC:
                    printf("Unspecified\n");
                    break;
                case AF_INET:
                    printf("AF_INET (IPv4)\n");
                    break;
                case AF_INET6:
                    printf("AF_INET6 (IPv6)\n");
                    break;
                case AF_NETBIOS:
                    printf("AF_NETBIOS (NetBIOS)\n");
                    break;
                default:
                    printf("Other %ld\n", ptr->ai_family);
                    break;
            }
            printf("\tSocket type: ");
            switch (ptr->ai_socktype) {
                case 0:
                    printf("Unspecified\n");
                    break;
                case SOCK_STREAM:
                    printf("SOCK_STREAM (stream)\n");
                    break;
                case SOCK_DGRAM:
                    printf("SOCK_DGRAM (datagram) \n");
                    break;
                case SOCK_RAW:
                    printf("SOCK_RAW (raw) \n");
                    break;
                case SOCK_RDM:
                    printf("SOCK_RDM (reliable message datagram)\n");
                    break;
                case SOCK_SEQPACKET:
                    printf("SOCK_SEQPACKET (pseudo-stream packet)\n");
                    break;
                default:
                    printf("Other %ld\n", ptr->ai_socktype);
                    break;
            }
            printf("\tProtocol: ");
            switch (ptr->ai_protocol) {
                case 0:
                    printf("Unspecified\n");
                    break;
                case IPPROTO_TCP:
                    printf("IPPROTO_TCP (TCP)\n");
                    break;
                case IPPROTO_UDP:
                    printf("IPPROTO_UDP (UDP) \n");
                    break;
                default:
                    printf("Other %ld\n", ptr->ai_protocol);
                    break;
            }
            printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
            printf("\tCanonical name: %s\n", ptr->ai_canonname);
        }
    
        freeaddrinfo(result);
        WSACleanup();
    
        return 0;
    }
    
    The above runs fine on both Windows XP and Windows 2000. I've highlighted the line of code in question above in bold. Here it is again:

    dwRetval = getaddrinfo(0, port, &hints, &result);

    According to the MSDN documentation:
    and
    Cool.

    Here is the deal: on Windows 2000 and Windows XP, if I pass a NULL to getaddrinfo:

    dwRetval = getaddrinfo(0, port, &hints, &result);

    The above test program runs fine and displays appropriate output.

    If I pass a character zero as a C string:

    dwRetval = getaddrinfo("0", port, &hints, &result);

    on Windows 2000, I get a Winsock 11001 error. On Windows XP, the program continues to run as it did when I passed a null as the nodename parameter.

    Why does Windows 2000 and Windows XP differ in this behavior?

    Thanks!

    Peace...
     
  2. lotuseclat79

    lotuseclat79

    Joined:
    Sep 12, 2003
    Messages:
    20,583
    Hi tomdkat,

    I would hazard a guess that the include files that contain the interface definitions for getaddrinfo are different between Windows 2000 and WinXP. The compiler would then compile in the difference for the respective system.

    A character string of "0" would be 30 (hex) and a null would be 00 (hex). Perhaps the WinXP code interface handles both, while Windows 2000 only handles one, and thus gives an error.

    -- Tom
     
  3. tomdkat

    tomdkat Retired Trusted Advisor Thread Starter

    Joined:
    May 6, 2006
    Messages:
    7,148
    Sounds like an acceptable explanation but I still wonder which implementation is behaving correctly. getaddrinfo() is a POSIX function so I'll see how a similar test program behaves on Linux.

    Thanks!

    Peace...
     
As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 733,556 other people just like you!

Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/757630

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice