windows下gethostbyname 调用失败 - 小众知识

windows下gethostbyname 调用失败

  标签: Socket
阅读:4422

    gethostbyname()函数属于WinSock API库,而在使用WinSock API之前,必须调用WSAStartup函数,

只有该函数成功返回(表示应用程序与WinSock库成功地建立起连接),

应用程序才可以调用其他Windows Sockets DLL中的函数。当程序将要结束时,又必须调用WSACleanup 函数进行清理工作,以便释放其占用的资源。

WSACleanup 函数用来结束Windows Sockets DLL的使用。


WSAStartup与WSACleanup

WSAStartup应该与WSACleanup成对使用,WSAStartup的功能是初始化Winsock DLL,WSACleanup是来解除与Socket库的绑定并且释放Socket库所占用的系统资源。


在Windows下,Socket是以DLL的形式实现的。在DLL内部维持着一个计数器,只有第一次调用WSAStartup才真正装载DLL,以后的 调用只是简单的增加计数器,而WSACleanup函数的功能则刚好相反,每调用一次使计数器减1,当计数器减到0时,DLL就从内存中被卸载!因此,你 调用了多少次WSAStartup,就应相应的调用多少次的WSACleanup.



gethostbyname返回NULL的问题分析

测试组提了一个奇怪的bug,一断开网络,并连接iPHone,程序就crash


于是开始分析。


无非就是加日志,找出crash函数。最后发现时使用网上的一个开源代码“etcp.h”的set_address(...)函数中crash。也就是调用gethostbyname处。


查看了一下错误码(h_errno),是HOST_NOT_FOUND。


于是网上找了个简单demo获取localhost,对比有网络连接和无网络连接状况下,前者能解析到127.0.0.1,后者直接返回HOST_NOT_FOUND。


打开host文件一看,水落石出:测试人员屏蔽了一个条目,localhost 127.0.0.1




网上看了下localhost的说明,说localhost代表本机,使用localhost的数据不用经过网卡,而直接使用127.0.0.1会经过网卡~




附上stackoverflow上的代码


#include <stdio.h>
 
#ifdef _WIN32
#  include "winsock.h"
#else
#  include <netdb.h>
#  include <arpa/inet.h>
#endif
 
static void initialise(void)
{
#ifdef _WIN32
    WSADATA data;
    if (WSAStartup (MAKEWORD(1, 1), &data) != 0)
    {
        fputs ("Could not initialise Winsock. ", stderr);
        exit (1);
    }
#endif
}
 
static void uninitialise (void)
{
#ifdef _WIN32
    WSACleanup ();
#endif
}
 
int main (int argc, char *argv[])
{
    struct hostent *he;
 
    if (argc == 1)
        return -1;
 
    initialise();
 
    he = gethostbyname (argv[1]);
    if (he == NULL)
    {
        switch (h_errno)
        {
            case HOST_NOT_FOUND:
                fputs ("The host was not found. ", stderr);
                break;
            case NO_ADDRESS:
                fputs ("The name is valid but it has no address. ", stderr);
                break;
            case NO_RECOVERY:
                fputs ("A non-recoverable name server error occurred. ", stderr);
                break;
            case TRY_AGAIN:
                fputs ("The name server is temporarily unavailable.", stderr);
                break;
        }
    }
    else
    {
        puts (inet_ntoa (*((struct in_addr *) he->h_addr_list[0])));
    }
 
    uninitialise ();
 
    return he != NULL;
}

​$ ./a.out stackoverflow.com

69.59.196.211

扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1