• socket http1


    /*****************************************************************/
    //name          : myhttp.h
    //function      : http 请求
    //copyright     : 
    //author        : mark
    //date          : 2008-05-13
    /**************************************************************/

    #ifndef _MY_HTTP_INCLUDE_
    #define _MY_HTTP_INCLUDE_

    #include <string>
    #include <map>
    #include <vector>

    class CAutoMem;

    #ifdef WIN32
    #include "WINSOCK2.H"
    #include <io.h>
    #endif


    class CMyHttp
    {
    private:
    #ifdef WIN32
     SOCKET m_fd;
     typedef SOCKET mysocket;
    #else
     int m_fd;
     typedef unsigned int mysocket;
    #endif

    #ifdef WIN32
    #define MY_INVALID_SOCKET INVALID_SOCKET
    #else
    #define MY_INVALID_SOCKET -1
    #endif

    #ifdef WIN32
    #define MY_SOCKET_ERROR SOCKET_ERROR
    #else
    #define MY_SOCKET_ERROR -1
    #endif

    #ifdef WIN32
    #define MYERRNO ::WSAGetLastError()
    #else
    #define MYERRNO errno
    #endif

     //超时最大值基数(单位毫秒)
     int m_timeoutmillisecond;
     //超时最小基数(单位:微秒,100000微秒,也即100毫秒)
     const int m_basicmicrosecond;
     //最大尝试次数
     const int MAXIMUMERRORNUMBER;
     //发送的请求原始串
     std::string m_req;
     //服务器 IP 和 port 对应表
     std::string m_srvip;
     int  m_srvport;
     int closesock(mysocket connectsocket);
     void release();

     //发送数据
     bool send(const CAutoMem &data);
     //设置 socket 阻塞和非阻塞
     bool setblocking(bool op);
     //检测 http 数据包是否完整
        bool checkhttppacket(const char* buffer);
    public:
     //默认最小超时基数100毫秒
     CMyHttp(const std::string& srvip ,int port,
                int timeoutmillisecond = 1500,
                int maxretrycount = 4);
     ~CMyHttp();

     //得到发送的请求
     const std::string GetReq();

     //建立连接
     int connect();

     int sendget(const std::string &url,
      const std::map<std::string,std::string> &values,
      bool URLENCODING = true);

     int sendpost(const std::string &url,
      const std::map<std::string,std::string> &values,
      bool URLENCODING = true);

     int sendpost(const std::string &url,const std::string &values);


     int sendpostxml(const std::string &url,
      const std::map<std::string,std::string> &values,
      bool URLENCODING = true);

     int sendpostxml(const std::string &url,const std::string &xml);

     //接收数据
     int receive(char *buff,int bufflen);
    };

    class CDNS
    {
    private:
     const std::string checkhost(const std::string &host);
    public:
     void parsehost(const std::string &host,std::vector<std::string> &addrs);
     void parsedomain(const std::string &host,std::vector<std::string> &addrs);
    };

    #endif


    /*****************************************************************/
    //name          : myhttp.cpp
    //function      :  http 请求
    //author        : mark
    //date          : 2008-05-13
    //modifier      : 2009-08-17,使用非阻塞socket,结合select
    //去判断数据发送和接收情况,默认最坏情况,从连接发起到发送接收完
    //成数据,都失败4次,耗时最大浪费接近 3 秒,其中发送1000 毫
    //秒,连接和接收各1000毫秒。实际每次操作的最大耗时是C:
    //设定A=(sum(1~(MAXIMUMERRORNUMBER - 1)) *1000) 毫秒,如果A大于
    //timeoutmillisecond,则相应MAXIMUMERRORNUMBER缩小,直到符合
    //A小于timeoutmillisecond;
    //设定B=(timeoutmillisecond + MAXIMUMERRORNUMBER * 100) 毫秒,
    //则最大耗时基本上小于B;最终是:A<C<B
    /***********************************************************************/

    #include "myhttp.h"
    #include "automem.h"
    #include "urlcode.h"
    #include "func_utility.h"
    #include "datetime.h"

    #include <map>
    #include <vector>
    using namespace std;

    #ifdef WIN32
    #include "WINSOCK2.H"
    #include <io.h> 
    #include "ws2tcpip.h"

    /*
    class CWSADATA
    {
    public:
    CWSADATA()
    {
    WSADATA wsaData;
    WSAStartup(0x101,&wsaData);
    }
    WSADATA()
    {
    WSACleanup();
    }
    };
    CWSADATA instance;
    */

    #else
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <time.h>
    #include <arpa/inet.h>
    #include <sys/ioctl.h>
    #include <netdb.h>
    //#include <sys/select.h>
    #endif

    CMyHttp::CMyHttp(const std::string& srvip ,int port,int timeoutmillisecond,
         int maxretrycount)
         :m_fd(MY_INVALID_SOCKET),
         m_timeoutmillisecond(timeoutmillisecond),
         m_basicmicrosecond(100000),
         MAXIMUMERRORNUMBER(maxretrycount),
         m_srvip(srvip),
         m_srvport(port)

     if(this->m_timeoutmillisecond > 5000 || this->m_timeoutmillisecond < 1000)
     {
      m_timeoutmillisecond = 1500;
     }
    }

    CMyHttp::~CMyHttp(void)
    {
     release();
    }

    void CMyHttp::release()
    {
     if(m_fd != MY_INVALID_SOCKET)
     {
      closesock(m_fd);
      m_fd = MY_INVALID_SOCKET;
     }
    }

    int CMyHttp::closesock(mysocket connectsocket)
    {
    #ifdef WIN32
     return ::closesocket(connectsocket);
    #else
     return ::close(connectsocket);
    #endif
    }

    //设置 socket 阻塞和非阻塞
    bool CMyHttp::setblocking(bool op)
    {
     unsigned long result = 0;
    #ifdef WIN32
     if(op)
     {
      result = 0;
     }
     else
     {
      result = 1;
     }
     result = ::ioctlsocket(m_fd,FIONBIO,&result);
    #else
     int fl = 0;
     if ((fl = fcntl(m_fd,F_GETFL,0)) == -1)
     {
      return false;
     }

     if(op)
     {
      fl &= ~O_NONBLOCK;  
     }
     else
     {
      fl |= O_NONBLOCK;
     }

     if (fcntl(m_fd,F_SETFL,fl) == -1)
     {
      result = 1;
     }
    #endif
     return result == 0?true:false;
    }

    //支持指数回退,重新连接
    int CMyHttp::connect()
    {
     int times = 1;
     int result = MY_INVALID_SOCKET;

     CDateTime start;
     //printf("%d,%s/n",times,dt.LongDateTimeWithMilliSec().c_str()); 
     while(result != 0 && times <= MAXIMUMERRORNUMBER)
     {
      release();
      //操作最大时间
      CDateTime now;
      if(now.SubMilliSecond(start) >= m_timeoutmillisecond)
      {
       break;
      }
      m_fd = socket(AF_INET,SOCK_STREAM,0);
      if(!this->setblocking(false))
      {
       times++;
       result = MYERRNO;
       continue;
      }
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = inet_addr(m_srvip.c_str());
      addr.sin_port = htons(m_srvport);  
      result = ::connect(m_fd,(struct sockaddr*)&addr,sizeof(addr));
      if (result == 0)
      {
       //连接成功
       return result;
      }
      result = MYERRNO;

      //开始用 select 去判断指定socket是否连接成功
      fd_set writeset,exceptset;
      FD_ZERO(&writeset);
      FD_SET(m_fd,&writeset);
      FD_ZERO(&exceptset);
      FD_SET(m_fd,&exceptset);
      struct timeval timeout = {0,0};
      timeout.tv_sec = 0;
      timeout.tv_usec = this->m_basicmicrosecond * times;
    #ifdef WIN32
      if (result != WSAEWOULDBLOCK)
      {
       times++;   
       continue;
      }
      do
      {
       result = select(0,0,&writeset,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #else
      if (result != EINPROGRESS)
      {
       times++;   
       continue;
      } 
      do
      {
       result = select(m_fd + 1,0,&writeset,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #endif

      if(result == MY_SOCKET_ERROR)
      {
       //发生错误
       result = MYERRNO;
       times++;
       continue;
      }
      else if(result == 0)
      {
       //超时发生,放弃连接   
       result = MY_SOCKET_ERROR;
       times++;
       continue;
      }

      if(FD_ISSET(m_fd,&writeset))
      {
       //完成连接
       result = 0;
    #ifdef WIN32
       //
    #else
       socklen_t len = sizeof(result);
       result = getsockopt(m_fd,SOL_SOCKET,SO_ERROR,(char*)&result,&len);
    #endif
      }
      else
      {
       //超时发生,放弃连接   
       result = MY_SOCKET_ERROR;
      }
      times++;
     }
     //CDateTime dt1;
     //printf("%d,%s/n",times,dt1.LongDateTimeWithMilliSec().c_str());

     return result;
    }

    bool CMyHttp::send(const CAutoMem &data)
    {
     int total_len = (int)data.Length();
     int sendlen = 0;
     int times = 1; 
     CDateTime start;
     //printf("%d,%s/n",times,dt.LongDateTimeWithMilliSec().c_str());
     while(sendlen < total_len 
      && times <= MAXIMUMERRORNUMBER)
     {
      //操作最大时间
      CDateTime now;
      if(now.SubMilliSecond(start) >= m_timeoutmillisecond)
      {
       break;
      }
      int newsend = ::send(m_fd,data.Get() + sendlen ,total_len - sendlen,0);
      if(newsend == MY_SOCKET_ERROR && MYERRNO != EAGAIN)
      {
       return false;
      }
      sendlen += (newsend>0?newsend:0);

      //使用select 去判断是否数据可以继续发  
      fd_set writeset,exceptset;
      FD_ZERO(&writeset);
      FD_SET(m_fd,&writeset);
      FD_ZERO(&exceptset);
      FD_SET(m_fd,&exceptset);
      struct timeval timeout = {0,0};
      timeout.tv_sec = 0;
      timeout.tv_usec = m_basicmicrosecond * times;
      int result = 0;
    #ifdef WIN32 
      do
      {
       result = select(0,0,&writeset,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #else 
      do
      {
       result = select(m_fd + 1,0,&writeset,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #endif 

      if(FD_ISSET(m_fd,&exceptset))
      {
       break;
      }

      //printf("%d/n",result);
      //内核缓冲区间有空间,数据可以继续发送
      if(FD_ISSET(m_fd,&writeset))
      {
       //
      }

      //发送无效果,算超时一次,算一次失败
      if(newsend <= 0)
      {
       times++;
      }
     }

     if(sendlen != total_len)
     {
      return false;
     }

     return true;
    }

    //接收数据,使用 http协议,尽量一次收取全部数据
    int CMyHttp::receive(char *buff,int bufflen)
    {
     if(buff == 0 || bufflen <= 0)
     {
      return 0;
     }

     //必须是1,否则select 会被至少执行两次,最后一次必须超时才能返回
     //如果要可配置,必须指定协议解析模块,能判断数据接收完毕后退出
     //一般情况下,使用http 1.0 协议,指定 connection :close ,
     //TCP 连接会进入同时关闭的情况,这样双方都不太消耗网络资源

     int received = 0;
     int times = 1;
     CDateTime start;
     //printf("%d,%s/n",times,start.LongDateTimeWithMilliSec().c_str());
     while(received < bufflen
      && times <= MAXIMUMERRORNUMBER)
     {

      //操作最大时间
      CDateTime now;
      if(now.SubMilliSecond(start) >= m_timeoutmillisecond)
      {
       break;
      }

      //开始用 select 去判断指定socket是否可以有数据读
      fd_set readset,exceptset;
      FD_ZERO(&readset);
      FD_SET(m_fd,&readset);
      FD_ZERO(&exceptset);
      FD_SET(m_fd,&exceptset);
      struct timeval timeout = {0,0};
      timeout.tv_sec = 0;
      timeout.tv_usec = this->m_basicmicrosecond * times;
      int result = 0;
    #ifdef WIN32
      do
      {
       result = ::select(0,&readset,0,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #else 
      do
      {
       result = ::select(m_fd + 1,&readset,0,&exceptset,&timeout);
      }while(result < 0 && MYERRNO == EINTR);
    #endif
      if(FD_ISSET(m_fd,&exceptset))
      {
       break;
      }

      //CDateTime dt1;
      //printf("vvvvv=%d,%s/n",times,dt1.LongDateTimeWithMilliSec().c_str());

      //printf("receive=%d/n",result);
      //有数据可以读取
      if(FD_ISSET(m_fd,&readset))
      {
    #ifdef WIN32
       int newrecv = ::recv(m_fd,buff + received,bufflen - received,0);
    #else
       int newrecv = ::recv(m_fd,buff + received,bufflen - received,MSG_WAITALL);
    #endif

       //printf("vv=%d,%d/n",newrecv,received);

       if(newrecv == MY_SOCKET_ERROR)
       {
        int err = MYERRNO;
    #ifdef WIN32
        if(err != EAGAIN && err != WSAEWOULDBLOCK)
        {
         break;
        }
    #else 
        if(err != EAGAIN && err != EWOULDBLOCK)
        {
         break;
        }
    #endif
       }
       else if(newrecv == 0)
       {
        //连接被关闭
        break;
       }
       else if(newrecv > 0)
       {
        //printf("aa=%d,%d/n",newrecv,received);
        received += newrecv;
        //数据包已经完整(这个方法是很不保险,如果数
        //据报过大,http 头完整后,但是http数据部分却可能接收不完整,比如resin3.2)
        //比较好的办法还是要通过socket 来判断数据是否接收完全
        if(this->checkhttppacket(buff))
        {
         break;
        }

        //不管收到了多少数据,算正常
        continue;    
       }
       else
       {
        //
       }
      }
      else
      {
       //算超时一次
       times++;
      }
     }
     //CDateTime dt1;
     //printf("%d,%d,%s/n",times,received,dt1.LongDateTimeWithMilliSec().c_str());
     return received;
    }

    //初步检测 http 数据包是否完整
    bool CMyHttp::checkhttppacket(const char* buffer)
    {
     const char * HTTP_HEAD_TAG = "/r/n/r/n"; 
     const char * HTTP_LINE_TAG = "/r/n";
     //const int HTTP_LINE_TAG_LEN = 2;
     //const int HTTP_HEAD_TAG_LEN = 4;

     char* p = strstr(buffer, HTTP_HEAD_TAG);
     if(0 != p)
     {
      //_nHeaderLen = p - buffer + HTTP_HEAD_TAG_LEN;
      return true;
     }

     p = strstr(buffer, HTTP_LINE_TAG);
     if(0 != p && p == buffer)
     {
      //_nHeaderLen = HTTP_LINE_TAG_LEN;
      return true;
     }

     return false;
    }

    int CMyHttp::sendpostxml(const std::string &url,
           const std::map<std::string,std::string> &values,
           bool URLENCODING)
    {
     int result = 1;
     const std::string STR = "http://";
     size_t pos = url.find(STR);
     if(pos == std::string::npos || url.length() <= 5)  
     {
      return -1;
     }
     size_t posmid = url.find("/",pos + STR.length());
     if(posmid == std::string::npos)
     {
      return -1;
     }

     std::string host = "";
     host = url.substr(pos + STR.length(),posmid - pos - STR.length());

     std::map<std::string,std::string>::const_iterator it;
     std::string req = "<?xml version=/"1.0/" encoding=/"gb2312/"?>";
     req += "<message>";
     for(it = values.begin();it != values.end();++it)
     {  
      if(URLENCODING)
      {
       CUrlCode urlcode;
       req += urlcode.encode(it->first);
       req += "=";
       req += urlcode.encode(it->second);
      }
      else
      {
       req += "<";
       req += it->first;
       req += ">";
       req += it->second;
       req += "</";
       req += it->first;
       req += ">";
      }
     }
     req += "</message>";

     std::string path = "";
     //path = "POST " + url + " HTTP/1.1/r/n";
     path = "POST " + url + " HTTP/1.0/r/n";
     path += "Accept: */*/r/n";
     path += "Accept-Language: zh-cn/r/n";
     path += "Accept-Encoding: gzip,default/r/n";
     path += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ";
     path += "Windows NT 5.1; SV1; TencentTraveler 4.0; .NET CLR 1.1.4322)/r/n";
     path += "Host: " + (host.length() > 0?host:m_srvip);
     req += ":" + util.stream_cast<std::string>(m_srvport);
     req += "/r/n";
     path += "Content-Length:";
     char buff[20] = {0};
     sprintf(buff,"%u/r/n",req.length());
     path += buff;
     //path += "Transfer-Encoding: chunked/r/n";
     path += "Connection: close/r/n";
     path += "Content-Type: application/x-www-form-urlencoded/r/n/r/n";
     req = path + req; 

     m_req = req;

     CAutoMem mem((int)req.length());
     memcpy(mem.Get(),req.c_str(),req.length());
     if(!this->send(mem))
     {
      result = -1;
     }

     return result;
    }

    int CMyHttp::sendpostxml(const std::string &url,const std::string &xml)
    {
     int result = 1;
     const std::string STR = "http://";
     size_t pos = url.find(STR);
     if(pos == std::string::npos || url.length() <= 5)  
     {
      return -1;
     }
     size_t posmid = url.find("/",pos + STR.length());
     if(posmid == std::string::npos)
     {
      return -1;
     }

     std::string host = "";
     host = url.substr(pos + STR.length(),posmid - pos - STR.length());


     std::string path = "";
     //path = "POST " + url + " HTTP/1.1/r/n";
     path = "POST " + url + " HTTP/1.0/r/n";
     path += "Accept: */*/r/n";
     path += "Accept-Language: zh-cn/r/n";
     path += "Accept-Encoding: gzip,default/r/n";
     path += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ";
     path += "Windows NT 5.1; SV1; TencentTraveler 4.0; .NET CLR 1.1.4322)/r/n";
     path += "Host: " + (host.length() > 0?host:m_srvip);
     req += ":" + util.stream_cast<std::string>(m_srvport);
     req += "/r/n";
     path += "Content-Length:";
     char buff[20] = {0};
     sprintf(buff,"%u/r/n",xml.length());
     path += buff;
     //path += "Transfer-Encoding: chunked/r/n";
     path += "Connection: close/r/n";
     path += "Content-Type: text/xml/r/n/r/n";
     m_req = path + xml;  

     CAutoMem mem((int)m_req.length());
     memcpy(mem.Get(),m_req.c_str(),m_req.length());
     if(!this->send(mem))
     {
      result = -1;
     }

     return result;
    }

    int CMyHttp::sendpost(const std::string &url,
           const std::map<std::string,std::string> &values,
           bool URLENCODING)
    {
     int result = 1;
     const std::string STR = "http://";
     size_t pos = url.find(STR);
     if(pos == std::string::npos || url.length() <= 5)
     {
      return -1;
     }
     size_t posmid = url.find("/",pos + STR.length());
     if(posmid == std::string::npos)
     {
      return -1;
     }

     std::string host = "";
     host = url.substr(pos + STR.length(),posmid - pos - STR.length());
     std::map<std::string,std::string>::const_iterator it;
     std::string req = "";
     for(it = values.begin();it != values.end();++it)
     {  
      if(URLENCODING)
      {
       CUrlCode urlcode;
       req += urlcode.encode(it->first);
       req += "=";
       req += urlcode.encode(it->second);
      }
      else
      {
       req += it->first;
       req += "=";
       req += it->second;
      }
      req += "&";
     }
     if(req.length() > 0 && req[req.length() - 1] == '&')
     {
      req = req.substr(0,req.length() - 1);
     }

     std::string path = "";

     //path = "POST " + url + " HTTP/1.1/r/n";
     path = "POST " + url + " HTTP/1.0/r/n";
     path += "Accept: */*/r/n";
     path += "Accept-Language: zh-cn/r/n";
     path += "Accept-Encoding: gzip,default/r/n";
     path += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ";
     path += "Windows NT 5.1; SV1; TencentTraveler 4.0; .NET CLR 1.1.4322)/r/n";
     path += "Host: " + (host.length() > 0?host:m_srvip);
     req += ":" + util.stream_cast<std::string>(m_srvport);
     req += "/r/n";
     path += "Content-Length:";
     char buff[20] = {0};
     sprintf(buff,"%u/r/n",req.length());
     path += buff;
     //path += "Transfer-Encoding: chunked/r/n";
     path += "Connection: close/r/n";
     path += "Content-Type: application/x-www-form-urlencoded/r/n/r/n";
     req = path + req;

     m_req = req;

     CAutoMem mem((int)req.length());
     memcpy(mem.Get(),req.c_str(),req.length());
     if(!this->send(mem))
     {
      result = -1;
     }

     return result;
    }

    int CMyHttp::sendpost(const std::string &url,
           const std::string &values)

    {
     int result = 1;

     std::string path = "";

     //path = "POST " + url + " HTTP/1.1/r/n";
     path = "POST " + url + " HTTP/1.0/r/n";
     path += "Accept: */*/r/n";
     path += "Accept-Language: zh-cn/r/n";
     path += "Accept-Encoding: gzip,default/r/n";
     path += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ";
     path += "Windows NT 5.1; SV1; TencentTraveler 4.0; .NET CLR 1.1.4322)/r/n";
     //path += "Host: " + "/r/n";
     path += "Content-Length:";
     char buff[20] = {0};
     sprintf(buff,"%u/r/n",values.length());
     path += buff;
     //path += "Transfer-Encoding: chunked/r/n";
     path += "Connection: close/r/n";
     path += "Content-Type: application/x-www-form-urlencoded/r/n/r/n";
     path = path + values;

     m_req = path;

     CAutoMem mem((int)path.length());
     memcpy(mem.Get(),path.c_str(),path.length());
     if(!this->send(mem))
     {
      result = -1;
     }

     return result;
    }

    int CMyHttp::sendget(const std::string &url,
          const std::map<std::string,std::string> &values,
          bool URLENCODING)
    {
     int result = 1;

     std::map<std::string,std::string>::const_iterator it;
     std::string req = "";
     for(it = values.begin();it != values.end();++it)
     {  
      if(URLENCODING)
      {
       CUrlCode urlcode;
       req += urlcode.encode(it->first);
       req += "=";
       req += urlcode.encode(it->second);
      }
      else
      {
       req += it->first;
       req += "=";
       req += it->second;
      }
      req += "&";
     }
     if(req.length() > 0 && req[req.length() - 1] == '&')
     {
      req = req.substr(0,req.length() - 1);
     }

     std::string uri = url;
     const std::string HTTP = "http://";
     MyString str;
     std::string host = "";
     if(str.strncasecmp(HTTP.c_str(),uri.c_str(),HTTP.length()) == 0)
     {
      size_t pos = uri.find("/", HTTP.length());
      if(pos != std::string::npos)
      {
       host = uri.substr(HTTP.length(),pos - HTTP.length()); 
       uri = uri.substr(pos);
      }
     }

     req = "GET " + uri + "?" + req; 
     //req += " HTTP/1.1/r/n";
     req += " HTTP/1.0/r/n";
     req += "Accept: */*/r/n";
     req += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;";
     req += "Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)/r/n";
     req += "Host: ";
     CFunc_Util util;
     req += host.length() > 0?host:m_srvip;
     req += ":" + util.stream_cast<std::string>(m_srvport);
     req += "/r/n";
     req += "Connection: close/r/n";
     req += "/r/n";

     m_req = req;

     CAutoMem mem((int)req.length());
     memcpy(mem.Get(),req.c_str(),req.length());

     if(!this->send(mem))
     {
      result = -1;
     }

     return result;
    }

    const std::string CMyHttp::GetReq()
    {
     return m_req;
    }

    void CDNS::parsehost(const std::string &host,std::vector<string> &addrs)

     std::string localhost = this->checkhost(host);

     //直接就是合法的 ip 地址
     if(inet_addr(localhost.c_str()) != INADDR_NONE)
     {
      addrs.push_back(localhost);
      return;
     }

     struct hostent *hptr = 0;
    #ifdef WIN32
     if((hptr = gethostbyname(localhost.c_str())) == 0)
     { 
      return ;
      /* 如果调用gethostbyname发生错误,返回1 */
     }
    #else
     int rc = 0;
     char buff[4096] = {0};
     struct hostent *result = 0;
     struct hostent myhostent;
     if(gethostbyname_r(localhost.c_str(),&myhostent,buff,sizeof(buff),&result,&rc) != 0)
     {
      return;
     }
     hptr = &myhostent;
    #endif

     /* 将主机的规范名打出来 */
     //printf("official hostname:%s/n",hptr->h_name);

     /* 主机可能有多个别名,将所有别名分别打出来 */
     //for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
     // printf("  alias:%s/n",*pptr);

     /* 根据地址类型,将地址打出来 */
     switch(hptr->h_addrtype)
     {
     case AF_INET:
     case AF_INET6:
      {  
       /* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */
       for(char **pptr = hptr->h_addr_list;*pptr != 0;pptr++)
       {
    #ifdef WIN32
        addrs.push_back(inet_ntoa(*((in_addr*)*pptr)));
    #else
        char str[128] = {0};
        inet_ntop(hptr->h_addrtype,*pptr,str,sizeof(str));
        addrs.push_back(str);
    #endif
       }
       break;
      }
     default:
      {
       break;
      }
     }
    }

    const std::string CDNS::checkhost(const std::string &host)
    {
     /* 调用gethostbyname()。调用结果都存在hptr中 */
     const std::string HTTP = "http://";
     const std::string HTTPS = "https://";

     std::string localhost = host;
     MyString mystr;
     if(mystr.strncasecmp(host.c_str(),HTTP.c_str(),HTTP.length()) == 0)
     {
      localhost = host.substr(HTTP.length());
     }

     if(mystr.strncasecmp(host.c_str(),HTTPS.c_str(),HTTPS.length()) == 0)
     {
      localhost = host.substr(HTTPS.length());
     }
     return localhost;
    }

    void CDNS::parsedomain(const std::string &host,std::vector<string> &addrs)

     std::string localhost = this->checkhost(host);
     //直接就是合法的 ip 地址
     if(inet_addr(localhost.c_str()) != INADDR_NONE)
     {
      addrs.push_back(localhost);
      return;
     }

     struct addrinfo hints;
     struct addrinfo *res = 0;
     memset(&hints,0,sizeof(struct addrinfo));

     hints.ai_addr = 0;
     hints.ai_addrlen = 0;
     hints.ai_canonname = 0;
     //hints.ai_family = AF_INET|AF_INET6;
     hints.ai_family = AF_INET;
     //hints.ai_flags = AI_NUMERICHOST|AI_CANNONAME;
     hints.ai_flags = AI_CANONNAME;
     hints.ai_next = 0;
     //hints.ai_protocol = IPPROTO_IP|IPPROTO_IPV4|IPPROTO_IPV6|IPPROTO_UDP|IPPROTO_TCP;
     hints.ai_protocol = IPPROTO_IP;
     //hints.ai_socktype = SOCK_STREAM|SOCK_DGRAM;
     hints.ai_socktype = SOCK_STREAM;
     int ret = 0;
     ret = getaddrinfo(localhost.c_str(),0,&hints,&res);
     if(ret != 0)
     { 
      freeaddrinfo(res);
      return ; 
     }

     struct addrinfo *ptr = res;
     while(ptr != 0)
     {
      //解析所要的域名信息 
      struct sockaddr_in * in = (struct sockaddr_in *)ptr->ai_addr;
    #ifdef WIN32
      addrs.push_back(inet_ntoa(in->sin_addr));
    #else
      char str[128] = {0};
      inet_ntop(in->sin_family,&in->sin_addr,str,sizeof(str));
      addrs.push_back(str);
    #endif
      ptr = ptr->ai_next;
     }
     freeaddrinfo(res);
    }

  • 相关阅读:
    【BZOJ4275】[ONTAK2015]Badania naukowe DP
    【BZOJ4295】[PA2015]Hazard 乱搞
    【BZOJ4297】[PA2015]Rozstaw szyn 树形DP
    Windows服务安装异常:System.Security.SecurityException: 未找到源,但未能搜索某些或全部事件日志。不可 访问的日志: Security
    直关的sql 联级更新语句
    c#经典俄罗斯方块 vs2012开发
    转 SSIS处理导入数据时, 存在的更新, 不存在的插入
    WM (Constants)
    数据仓库的模型设计
    BI (商业智能)
  • 原文地址:https://www.cnblogs.com/thbCode/p/4390187.html
Copyright © 2020-2023  润新知