网络编程之基本函数一

 

hostent *gethostbyname(const char *name);
    这个函数的传入值是域名或者主机名,例如"www.google.cn"等等。传出值,是一个hostent的结构。如果函数调用失败,将返回NULL。

 struct hostent
    {
        char    *h_name;               
        char    **h_aliases;
        int     h_addrtype;
        int     h_length;
        char    **h_addr_list;
        #define h_addr h_addr_list[0]
    };

    hostent->h_name
    表示的是主机的规范名。例如www.google.com的规范名其实是www.l.google.com。
    hostent->h_aliases
    表示的是主机的别名.www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
    hostent->h_addrtype
    表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)
    hostent->h_length
    表示的是主机ip地址的长度
    hostent->h_addr_list
    表示的是主机的ip地址,注意,这个是以网络字节序存储的。不能直接用printf带%s参数来打印,所以到真正需要打印出这个IP的话,需要调用inet_ntop()。

    linux 下可以调用const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
    这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。返回指向dst的一个指针。如果函数调用错误,返回值是NULL。

以下是简单的例子:

   因为windows中没有inet_ntop函数可以使用,所以必须重写这个函数,幸亏有人已经做过这样的事情。

// PrintAddress.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <WinSock.h>
#include <iostream>

using namespace std;
#pragma comment(lib,"ws2_32.lib")

#define IN6ADDRSZ 128
#define INT16SZ   16
#define INET6_ADDRSTRLEN 128

#ifdef _WIN32

typedef struct _BASE 
{
    long base;
    long len;
}BASE;

static const char* inet_ntop4(const u_char* src, char* dst, size_t size)
{
    static const char fmt[] = "%u.%u.%u.%u";
    char tmp[sizeof("255.255.255.255")];

    int l = sprintf_s(tmp,"%d.%d.%d.%d", src[0], src[1], src[2], src[3]);
    if(l <= 0 ||l >size)
    {
        return NULL;
    }

    strcpy_s(dst, size, tmp);
    return dst;
}

static const char* inet_ntop6(const u_char* src, char* dst, size_t size)
{
    /* Note that int32_t and int16_t need only be "at least" large enough

    * to contain a value of the specified size.  On some systems, like

    * Crays, there is no such thing as an integer variable with 16 bits.

    * Keep this in mind if you think this function should have been coded

    * to use pointer overlays.  All the world's not a VAX. */

    char  tmp [INET6_ADDRSTRLEN+1];
    char *tp;
    BASE best, cur;
    u_long words [IN6ADDRSZ / INT16SZ];
    int    i;


    /* Preprocess:

    *  Copy the input (bytewise) array into a wordwise array.

    *  Find the longest run of 0x00's in src[] for :: shorthanding. */

    memset (words, 0, sizeof(words));

    for (i = 0; i < IN6ADDRSZ; i++)
    {
        words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
    }

    best.base = -1;
    cur.base  = -1;

    for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
    {
        if (words[i] == 0)
        {
            if (cur.base == -1)
            {
                cur.base = i, cur.len = 1;
            }
            else cur.len++;
        }
        else if (cur.base != -1)
        {
            if (best.base == -1 || cur.len > best.len)
            {
                best = cur;
            }
            cur.base = -1;
        }

    }
    if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
    {
        best = cur;
    }
    if (best.base != -1 && best.len < 2)
    {
        best.base = -1;
    }

    /* Format the result. */
    tp = tmp;
    for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
    {
        /* Are we inside the best run of 0x00's? */
        if (best.base != -1 && i >= best.base && i < (best.base + best.len))
        {
            if (i == best.base)
            {
                *tp++ = ':';
            }
            continue;
        }
        /* Are we following an initial run of 0x00s or any real hex? */
        if (i != 0)
        {
            *tp++ = ':';
        }
        /* Is this address an encapsulated IPv4?*/
        if (i == 6 && best.base == 0 &&(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
        {
            tp += strlen(tp);
            break;
        }
        tp += sprintf (tp, "%lX", words[i]);
    }

    /* Was it a trailing run of 0x00's?  */
    if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
    {
        *tp++ = ':';
    }
    *tp++ = '\0';


    /* Check for overflow, copy, and we're done.

    */

    if ((size_t)(tp - tmp) > size)
    {
        return NULL;
    }
    strcpy_s(dst, size, tmp);
    return dst;
}

const char* inet_ntop(int af, void *src, char *dst, size_t size)

{
    switch (af) 
    {
    case AF_INET :
        return inet_ntop4 ((u_char*)src, dst, size);
#ifdef INET6
    case AF_INET6:
        return inet_ntop6 ((const u_char*)src, dst, size);
#endif
    default :
        return NULL;
    }
} 

int _tmain(int argc, _TCHAR* argv[])
{
    char str[32];
    char* ip = "www.baidu.com";

    WSAData wsaData;
    if(WSAStartup(0x22, &wsaData) != 0)
    {
        return 0;
    }


    LPHOSTENT host = gethostbyname(ip);
    if(host != NULL)
    {
        cout<<host->h_name<<endl;
        cout<<host->h_length<<endl;
        for(char** ptr = host->h_aliases; *ptr != NULL; ptr++)
        {
            cout<<"Alias:"<<*ptr<<endl;
        }
        for(char** ptr = host->h_addr_list; *ptr != NULL; ptr++)
        {
            cout<<"Address:"<<inet_ntop(AF_INET,ptr, str, sizeof(str))<<endl;
        }
        cout<<"First address:"<<inet_ntop(AF_INET, host->h_addr, str, sizeof(str))<<endl;
    }
    system("pause");
    return 0;
}
#endif

输出结果为:

image

 

posted @ 2012-11-30 16:58  拿枪的程序员  阅读(275)  评论(0编辑  收藏  举报