[原]socket通訊實現域名解析

//extern     unsigned char gSntpServerIP[20];
int GetNTPTime(unsigned char *ntpServerIP,unsigned int ntpPort,unsigned int  *data)  
{  
    int sockfd=0;  
    char ntpServerName[20];
    
      
    STNP_Header H_NTP;        
    
    H_NTP.LiVnMode = 0x1b;//LI(2bit )  VN(3bit 版本)      Mode(3bit客戶端模式)  
    H_NTP.Stratum = STRATUM;
    H_NTP.Poll = POLL;
    H_NTP.Precision =PREC;
    
    memset(ntpServerName,0,sizeof(ntpServerName));
    sprintf(ntpServerName,"%s",ntpServerIP);

    NF_LOG(DEBUG_K,"@_@,sync time from %s,H_NTP.Stratum=%d\n", ntpServerName,H_NTP.Stratum); 

    #if 0//不能解析域名的方式
    struct sockaddr_in server;
    server.sin_family = AF_INET;  
    server.sin_addr.s_addr = gethostIPbyname((const char*)ntpServerName);  
    server.sin_port = htons(ntpPort);
    if(-1 == (int)server.sin_addr.s_addr)  
    {
        NF_LOG(ERROR_L,"[%s,%d]s_addr error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }
    
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if(sockfd<0)  
    {  
        NF_LOG(ERROR_L,"[%s,%d]socket error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }
    #endif

    
    #if 1//getaddrinfo能夠解析域名的方式
    int  rc;
    addrinfo hints, *res = NULL,*cur=NULL;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_protocol = IPPROTO_UDP;
    char port[10];
    memset(port,0,sizeof(port));
    sprintf(port,"%d",ntpPort);
    rc = getaddrinfo((const char*)ntpServerName, port, &hints, &res);

    if (rc != 0) 
    {
        NF_LOG(ERROR_L,"[%s,%d]getaddrinfo error...rc=%s\n",__FUNCTION__,__LINE__,gai_strerror(rc));
        
        return -1;  
    }

    struct sockaddr_in *addr;
    char m_ipaddr[16];
    memset(m_ipaddr,0,sizeof(m_ipaddr));
    
     for (cur = res; cur != NULL; cur = cur->ai_next) {
        addr = (struct sockaddr_in *)cur->ai_addr;
        inet_pton(AF_INET, m_ipaddr, (void *)addr);
        inet_ntop(AF_INET, (void *)&addr, m_ipaddr, 16);// 反轉換
        printf("@_@:Parse ip:%s\n",m_ipaddr);
    }
    
    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sockfd < 0) 
    {
        NF_LOG(ERROR_L,"[%s,%d]socket error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }
    #endif

    //if(sendto(sockfd, (void*)&H_NTP, sizeof(STNP_Header), 0, (struct sockaddr*)&server, sizeof(server))<0)  
    if(sendto(sockfd, (void*)&H_NTP, sizeof(STNP_Header), 0, res->ai_addr, res->ai_addrlen)<0)  
    {  
        NF_LOG(ERROR_L,"[%s,%d]sendto error...\n",__FUNCTION__,__LINE__); 
        return -1;  
    }  
      
    fd_set r;  
    FD_ZERO(&r);  
    FD_SET(sockfd, &r);  
    struct timeval timeout;  
    timeout.tv_sec = 10;  
    timeout.tv_usec = 0;  
      
    if(1 != select(sockfd+1, &r, NULL, NULL, &timeout))  
    {
        NF_LOG(ERROR_L,"[%s,%d] select error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }
    
    if(recv(sockfd, (void*)data, 48, 0)<0) //48 後續要定義成宏
    {
        NF_LOG(ERROR_L,"[%s,%d]recv error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }
    
    close(sockfd);  
    return 0;  
}  
getaddrinfo函數

使用到的結構體理解
addrinfo
sockaddr_in
/* Internet address.  */

typedef __u16 in_port_t;
typedef __u32 in_addr_t;服務器

struct in_addr
  {
    in_addr_t s_addr;
  };



/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;            /* Port number.  */
    struct in_addr sin_addr;        /* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
               __SOCKADDR_COMMON_SIZE -
               sizeof (in_port_t) -
               sizeof (struct in_addr)];
  };

 

將sockaddr_in格式的地址,打印成點分十進制的方式:
 
 

  struct sockaddr_in *addr;
  char m_ipaddr[16];
  memset(m_ipaddr,0,sizeof(m_ipaddr));網絡


for
(cur = res; cur != NULL; cur = cur->ai_next) { addr = (struct sockaddr_in *)cur->ai_addr; inet_pton(AF_INET, m_ipaddr, (void *)addr); inet_ntop(AF_INET, (void *)&addr, m_ipaddr, 16);// 反轉換 printf("@_@:Parse ip:%s\n",m_ipaddr); }

 

 

======socket

須要區分下這些結構體的差別函數

sockaddr_in 用於IPV4的網絡Internet IP/port,因此其結構成員sin_family必須填入AF_INET??優化

struct sockaddr_in server;
    server.sin_family = AF_INET;  
    server.sin_addr.s_addr = gethostIPbyname((const char*)ntpServerName);  
    server.sin_port = htons(ntpPort);
    if(-1 == (int)server.sin_addr.s_addr)  
    {
        NF_LOG(ERROR_L,"[%s,%d]s_addr error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }

 

   addrinfo  spa

addrinfo hints, *res = NULL,*cur=NULL;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_protocol = IPPROTO_UDP;
    char port[10];
    memset(port,0,sizeof(port));
    sprintf(port,"%d",ntpPort);
    rc = getaddrinfo((const char*)ntpServerName, port, &hints, &res);

根據地址域獲取到的信息存放在res.net

操做res獲取的地址和port信息來連接及發送數據:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sockfd < 0) 
    {
        NF_LOG(ERROR_L,"[%s,%d]socket error...\n",__FUNCTION__,__LINE__);
        return -1;  
    }

if(sendto(sockfd, (void*)&H_NTP, sizeof(NTP_Header), 0, res->ai_addr, res->ai_addrlen)<0)  
    {  
        NF_LOG(ERROR_L,"[%s,%d]sendto error...\n",__FUNCTION__,__LINE__); 
        return -1;  
    } 

 

 

 getaddrinfo可以獲取多個ip地址,這裏能夠去bind嘗試看看哪一個能夠通來優化:code

https://blog.csdn.net/an_zhenwei/article/details/8591729

 

 

 

待確認:gethostIPbyname 不能解析地址域嗎???當時之因此不能解析的緣由是因爲沒有添加DNS服務器在resolv.conf
相關文章
相關標籤/搜索