域名转ip地址编程实现

linux平台:

首先ip地址在编程中有两种形式,一种是十进制点分式,如192.168.2.187,另外一种是用一个32位的整数表示(ipv4)。

域名转换成ip地址,首先调用函数gethostbyname,转换结果存在一个hostent结构体中。转换成功后的ip地址存放在hostent最后一个字段中:

struct    hostent {
    const char    *h_name;    			// official name of host
    char    **h_aliases;    			// alias list
    short    h_addrtype;    			// host address type
    short    h_length;    // length of address
    char    **h_addr_list;    // list of addresses from name server
#define    h_addr    h_addr_list[0]    // address, for backward compatiblity
};

typedef uint32_t in_addr_t;


struct in_addr
{
  in_addr_t s_addr;
};


解释一下:

h_name – 地址的正式名称。 
h_aliases – 空字节-地址的预备名称的指针。 
h_addrtype –地址类型; 通常是AF_INET。  
h_length – 地址的比特长度。 
h_addr_list – 零字节-主机网络地址指针。网络字节顺序。 
h_addr - h_addr_list中的第一地址。 
gethostbyname() 成 功时返回一个指向结构体 hostent 的指针,或者 是个空 (NULL) 指针。


虽然看起来h_addr_list[0],看起来是一个char*,但实际上是一个uint32_t,这是ip地址的32位整数表示,如果需要转换成10进制点分法字符串表示再调用inet_ntoa()函数即可。

下面这个函数演示了具体的用法:

bool Connect(const char* pszIp, int nPort)
{
    struct hostent* pHostent = NULL;
    char* host = NULL;

    struct sockaddr_in addrSrv;
    memset(&addrSrv, 0, sizeof(addrSrv));
    addrSrv.sin_addr.s_addr = ::inet_addr(pszIp);
    if (addrSrv.sin_addr.s_addr == INADDR_NONE)
    {
        pHostent = ::gethostbyname(pszIp);
        if (pHostent != NULL)
        {
            host = inet_ntoa(*((struct in_addr *)pHostent->h_addr));
            std::cout << pszIp << "=" << host << std::endl;
        }
        else
        {
            herror("gethostbyname error");
            std::cout << std::endl;
            return false;
        }
    }
    else
        host = (char*)pszIp;

    if (Socket.Connect(host, nPort))
        return true;

    std::cout << "Unable to connect to server " << pszIp << ":" << nPort << std::endl;
    return false;
}

这里的函数无论外部传入的参数是域名还是ip地址都可以正确调用socket的connect()函数进行连接。

注意:在使用 gethostbyname() 的时候,你不能用perror() 打印错误信息 (因为 errno 没有使用),你应该调用 herror()。herror()函数签名如下:

void herror(const char *s);


另外Windows上这个功能也类似:

//pszServer无论是ip地址还是域名都可以正确连接
BOOL CIUSocket::Connect(const char* pszServer, short nPort)
{
	m_hSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if(m_hSocket == INVALID_SOCKET)
		return FALSE;

	long tmSend = 3*1000L;
	long tmRecv = 3*1000L;
	long noDelay = 1;
	setsockopt(m_hSocket, IPPROTO_TCP, TCP_NODELAY,(LPSTR)&noDelay, sizeof(long));
	setsockopt(m_hSocket, SOL_SOCKET,  SO_SNDTIMEO,(LPSTR)&tmSend, sizeof(long));
	setsockopt(m_hSocket, SOL_SOCKET,  SO_RCVTIMEO,(LPSTR)&tmRecv, sizeof(long));

	struct sockaddr_in addrSrv = {0}; 
	struct hostent* pHostent = NULL;
	unsigned int addr = 0;
	

	if((addrSrv.sin_addr.s_addr=inet_addr(pszServer)) == INADDR_NONE)
	{
		pHostent = ::gethostbyname(pszServer) ;
		if (!pHostent) 
			return FALSE;
		else
			addrSrv.sin_addr.s_addr = *((unsigned long*)pHostent->h_addr);
	}

	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons((u_short)nPort); 
	if(::connect(m_hSocket, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == SOCKET_ERROR)
		return FALSE;


	m_bConnected = TRUE;

	return TRUE;
}




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值