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