域名转ip地址编程实现

    xiaoxiao2021-12-14  19

    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; }

    转载请注明原文地址: https://ju.6miu.com/read-963631.html

    最新回复(0)