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

socket http1的更多相关文章

  1. c++如何使用SOCKET 发送HTTP1.1 GET POST请求包

    如何使用SOCKET 发送HTTP1.1 GET POST请求包 分类: 无线通信 C/C++2009-10-29 10:58 14259人阅读 评论(15) 收藏 举报 socket服务器actio ...

  2. C# HTTP1.0 1.1 2.0与HTTPS 、TCP/IP协议的UDP与TCP、 Socket介绍与WebSocket

    一.HTTP1.0 1.1 2.0和HTTPS 1.HTTP协议是什么? HTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol.它是从WEB服务器传输超文 ...

  3. 如何使用SOCKET 发送HTTP1.1 GET POST请求包

    http://blog.csdn.net/yc0188/article/details/4741871 http://docs.linuxtone.org/ebooks/C&CPP/c/ch3 ...

  4. JAVA通信系列一:Java Socket技术总结

    本文是学习java Socket整理的资料,供参考. 1       Socket通信原理 1.1     ISO七层模型 1.2     TCP/IP五层模型 应用层相当于OSI中的会话层,表示层, ...

  5. HTML5:web socket 和 web worker

    a:hover { cursor: pointer } 做练习遇到了一个选择题,是关于web worker的,问web worker会不会影响页面性能?补习功课之后,答案是不会影响. 查阅了相关资料学 ...

  6. socket了解(转)

    http://blog.chinaunix.net/uid-26000296-id-3758651.html http://blog.csdn.net/mengyafei43/article/deta ...

  7. iOS之 HTTP、Socket、TCP的区别(易混

    一.HTTP 是一种超文本传输协议,全名hypertext transfer protocol,从字面意思上可以看出该协议用于规定客户端与服务端之间的传输规则, 传输的内容不限于文本(任意类型的数据) ...

  8. 阻塞通信之Socket编程

    Socket通信,主要是基于TCP协议的通信.本文从Socket通信(代码实现).多线程并发.以及TCP协议相关原理方面 介绍 阻塞Socket通信一些知识. 本文从服务器端的视角,以“Echo Se ...

  9. PHP socket编程需要了解的一些基本知识

    前面讲到了 fsockopen 的各种情况,其中涉及了很多其它知识,比如chunked分段传输,Keep-Alive,HTTP头字段等额外的知识,如果对这些知识一知半解,会影响对 PHP 的 sock ...

随机推荐

  1. Python-in is == 区别

    in 判断单个元素是否在序列中, 对字典来说只能判断key,在不在关系 print("ab" in "abcdefg") print("abc&quo ...

  2. Python练习题 035:Project Euler 007:第10001个素数

    本题来自 Project Euler 第7题:https://projecteuler.net/problem=7 # Project Euler: Problem 7: 10001st prime ...

  3. Jetson AGX Xavier/Ubuntu安装QT

    安装QT命令 sudo apt-get install qt5-default qtcreator -y 如果出现错误:unknow module webenginewidgets serialpor ...

  4. 创建自定义视图在Android矩阵效果画布教程

    介绍 下面是一个快速教程,教你如何在Android中创建自定义视图.自定义视图创建一个矩阵雨效果. 本教程发布在http://www.androidlearner.com/. 背景 下面是关于如何工作 ...

  5. Dockerize ASP。净样板项目

    Get the source code from the Github repository. 介绍 在这篇文章中,我将一步步地向你展示如何在Docker上运行ABP模块零核心模板.然后,我们将讨论其 ...

  6. 加快ASP。NET Core WEB API应用程序。第2部分

    下载source from GitHub 使用各种方法来增加ASP.NET Core WEB API应用程序的生产力 介绍 第1部分.创建测试RESTful WEB API应用程序第2部分.增加了AS ...

  7. ActiveMQ详细入门教程系列(一)

    一.什么是消息中间件 两个系统或两个客户端之间进行消息传送,利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,它可以在分布式环境下 ...

  8. ubuntu 19.10 中防火墙iptables配置

    $sudo which iptables   /usr/sbin/iptables说明有安装 如果没有安装,那么使用sudo apt-get install iptables 安装. 刚装机,是这个样 ...

  9. JSON,数组根据字段多次分组

    我们在前端开发过程中,遇到json对象,有时会需要多次分组.比如说,先按照是业务分组,然后再按照产品线分组,然后通过table或其他方式展示或操作 var obj1=[ { "demp&qu ...

  10. 【C语言编程入门】Do you know 函数?不知道了吧,我来告诉你!

    ☆ 函数 在前面我们已经讲过了一些简单的函数,如程序的主函数main().标准输出函数printf().在C语言中,大多数功能都是依靠函数来实现的.But,你知道什么是函数吗?我猜你肯定不知道. 那么 ...