const INT RECV_BUFFER_LEN = 1024;
//
// Construction/Destruction
//
DLRequest::DLRequest()
{
}
DLRequest::~DLRequest()
{
}
//*******************************************************************************************************
// GetHostAddress:
// Resolve using DNS or similar(WINS,etc) the IP
// address for a domain name such as www.wdj.com.
//*******************************************************************************************************
DWORD DLRequest::GetHostAddress(LPCSTR host)
{
struct hostent *phe;
char *p;
phe = gethostbyname( host );
if(phe==NULL)
return 0;
p = *phe->h_addr_list;
return *((DWORD*)p);
}
//*******************************************************************************************************
// SendString:
// Send a string(null terminated) over the specified socket.
//*******************************************************************************************************
void DLRequest::SendString(SOCKET sock,LPCSTR str)
{
send(sock,str,strlen(str),0);
}
//*******************************************************************************************************
// ValidHostChar:
// Return TRUE if the specified character is valid
// for a host name, i.e. A-Z or 0-9 or -.:
//*******************************************************************************************************
BOOL DLRequest::ValidHostChar(char ch)
{
return( isalpha(ch) || isdigit(ch)
|| ch=='-' || ch=='.' || ch==':' );
}
void DLRequest::ParseURL(std::string url,LPSTR protocol,int lprotocol, LPSTR host,int lhost,LPSTR request,int lrequest,int *port)
{
char *work,*ptr,*ptr2;
*protocol = *host = *request = 0;
*port=80;
work = _strdup(url.c_str());
_strupr_s(work, strlen(work) +1);
ptr = strchr(work,':'); // find protocol if any
if(ptr!=NULL)
{
*(ptr++) = 0;
lstrcpyn(protocol,work,lprotocol);
}
else
{
lstrcpyn(protocol,"HTTP",lprotocol);
ptr = work;
}
if( (*ptr=='/') && (*(ptr+1)=='/') ) // skip past opening /'s
ptr+=2;
ptr2 = ptr; // find host
while( ValidHostChar(*ptr2) && *ptr2 )
ptr2++;
*ptr2=0;
lstrcpyn(host,ptr,lhost);
lstrcpyn(request,url.c_str() + (ptr2-work),lrequest); // find the request
ptr = strchr(host,':'); // find the port number, if any
if(ptr!=NULL)
{
*ptr=0;
*port = atoi(ptr+1);
}
free(work);
}
int DLRequest::RequestHttpDL(std::string url)
{
WSADATA WsaData;
char protocol[20];
char host[256];
int l,port,chars,err;
char request[256] = { 0 };
ParseURL(url,protocol,sizeof(protocol),host,sizeof(host), // Parse the URL
request,sizeof(request),&port);
if(strcmp(protocol,"HTTP"))
return 1;
err = WSAStartup (0x0101, &WsaData); // Init Winsock
if(err!=0)
return 1;
SOCKET sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
return 1;
}
SOCKADDR_IN sin;
sin.sin_family = AF_INET; //Connect to web sever
sin.sin_port = htons( (unsigned short)port );
sin.sin_addr.s_addr = GetHostAddress(host);
if( connect (sock,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) ) )
{
return 1;
}
if( !*request )
lstrcpyn(request,"/",sizeof(request));
//格式化请求头
std::string strHeadSend("GET ");
strHeadSend += request;
strHeadSend += " HTTP/1.0\r\n";
strHeadSend += "Accept: */*\r\n";
strHeadSend += "Accept-Language: en-us\r\n";
strHeadSend += "Host: ";
strHeadSend += host;
strHeadSend += "\r\n\r\n";
//发送请求头
SendString( sock, strHeadSend.c_str() );
// MemBuffer headersBuffer,messageBuffer;
//
// MemBufferCreate(&headersBuffer );
chars = 0;
BOOL done;
done = FALSE;
char buffer[RECV_BUFFER_LEN] = { 0 };
int nPosition = 0;
while(!done)
{
l = recv(sock,buffer + nPosition,1,0);
if(l<0)
done=TRUE;
switch(*(buffer+nPosition))
{
case '\r':
break;
case '\n':
if(chars==0)
done = TRUE;
chars=0;
break;
default:
chars++;
break;
}
nPosition++;
}
//获得状态码
//200 OK 客户端请求成功
//400 Bad Request 客户端有语法错误,不能被服务器所理解
//401 Unauthorized 请求未经授权
//403 Forbidden 服务器收到请求,但是拒绝提供服务
//404 Not Found 请求资源不存在,可能输入了错误的URL
//500 Internal Server Error 服务器发生了不可预期的错误
//503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
CHAR szHttpVer[ 32 ] = { 0 };
INT nStatusCode = 0;
sscanf( buffer, "%s %d", szHttpVer, &nStatusCode );
if( 200 != nStatusCode )
{
if( 403 == nStatusCode || 503 == nStatusCode )
{
}
else
{
return 1;//失败
}
}
//获得文件长度
INT nFileLength = 0;
char* pFindCL = strstr( buffer, "Content-Length:" );
if( pFindCL != NULL )
{
CHAR szTemp[ 32 ] = { 0 };
sscanf( pFindCL, "%s %d", szTemp, &nFileLength );
}
//得到路径
char szDirectory[ MAX_PATH ] = { 0 };
GetCurrentDirectory( MAX_PATH, szDirectory );
std::string strFileName = szDirectory;
strFileName += request;
std::replace( strFileName.begin(), strFileName.end(), '\\', '/' );
//获得原始文件名称
std::string strOrigFileName = strFileName;
// int findPos = strFileName.find_last_of( "/" );
// if( findPos != string::npos )
// {
// strOrigFileName = strFileName.substr( findPos + 1 );
// }
strFileName += ".tmp"; //文件名称修改成一个临时文件名称,下载完毕后还原
FILE* pFile = NULL;
fopen_s(&pFile, strFileName.c_str(), "wb" ); //打开一个文件,写,如果文件存在,则清空
if( !pFile )
{
return 1;
}
INT nRecvedSize = 0; //已经接收的数量
INT nPos = 0; //偏移
while( TRUE )
{
INT nRecv = recv( sock, buffer + nPos, RECV_BUFFER_LEN - nPos, 0 );
if( nRecv > 0 )
{
nRecvedSize += nRecv;
nPos += nRecv;
if( nPos >= RECV_BUFFER_LEN && nRecvedSize < nFileLength )//BUFF满了,但文件没有接受完毕
{
//内容写到文件中
fwrite( buffer, RECV_BUFFER_LEN, 1, pFile );
nPos = 0;
}
else if( nRecvedSize >= nFileLength )//文件接收完毕
{
//文件接收完毕,保存内容
fwrite( buffer, nPos, 1, pFile );
fclose( pFile );
//修改文件名称
rename( strFileName.c_str(), strOrigFileName.c_str() );
break;
}
}
else if( 0 == nRecv )
{
//socket关闭
break;
}
else
{
int nErrCode = WSAGetLastError();
break;
}
}
closesocket(sock);
return 0;
}
//
// Construction/Destruction
//
DLRequest::DLRequest()
{
}
DLRequest::~DLRequest()
{
}
//*******************************************************************************************************
// GetHostAddress:
// Resolve using DNS or similar(WINS,etc) the IP
// address for a domain name such as www.wdj.com.
//*******************************************************************************************************
DWORD DLRequest::GetHostAddress(LPCSTR host)
{
struct hostent *phe;
char *p;
phe = gethostbyname( host );
if(phe==NULL)
return 0;
p = *phe->h_addr_list;
return *((DWORD*)p);
}
//*******************************************************************************************************
// SendString:
// Send a string(null terminated) over the specified socket.
//*******************************************************************************************************
void DLRequest::SendString(SOCKET sock,LPCSTR str)
{
send(sock,str,strlen(str),0);
}
//*******************************************************************************************************
// ValidHostChar:
// Return TRUE if the specified character is valid
// for a host name, i.e. A-Z or 0-9 or -.:
//*******************************************************************************************************
BOOL DLRequest::ValidHostChar(char ch)
{
return( isalpha(ch) || isdigit(ch)
|| ch=='-' || ch=='.' || ch==':' );
}
void DLRequest::ParseURL(std::string url,LPSTR protocol,int lprotocol, LPSTR host,int lhost,LPSTR request,int lrequest,int *port)
{
char *work,*ptr,*ptr2;
*protocol = *host = *request = 0;
*port=80;
work = _strdup(url.c_str());
_strupr_s(work, strlen(work) +1);
ptr = strchr(work,':'); // find protocol if any
if(ptr!=NULL)
{
*(ptr++) = 0;
lstrcpyn(protocol,work,lprotocol);
}
else
{
lstrcpyn(protocol,"HTTP",lprotocol);
ptr = work;
}
if( (*ptr=='/') && (*(ptr+1)=='/') ) // skip past opening /'s
ptr+=2;
ptr2 = ptr; // find host
while( ValidHostChar(*ptr2) && *ptr2 )
ptr2++;
*ptr2=0;
lstrcpyn(host,ptr,lhost);
lstrcpyn(request,url.c_str() + (ptr2-work),lrequest); // find the request
ptr = strchr(host,':'); // find the port number, if any
if(ptr!=NULL)
{
*ptr=0;
*port = atoi(ptr+1);
}
free(work);
}
int DLRequest::RequestHttpDL(std::string url)
{
WSADATA WsaData;
char protocol[20];
char host[256];
int l,port,chars,err;
char request[256] = { 0 };
ParseURL(url,protocol,sizeof(protocol),host,sizeof(host), // Parse the URL
request,sizeof(request),&port);
if(strcmp(protocol,"HTTP"))
return 1;
err = WSAStartup (0x0101, &WsaData); // Init Winsock
if(err!=0)
return 1;
SOCKET sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
return 1;
}
SOCKADDR_IN sin;
sin.sin_family = AF_INET; //Connect to web sever
sin.sin_port = htons( (unsigned short)port );
sin.sin_addr.s_addr = GetHostAddress(host);
if( connect (sock,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) ) )
{
return 1;
}
if( !*request )
lstrcpyn(request,"/",sizeof(request));
//格式化请求头
std::string strHeadSend("GET ");
strHeadSend += request;
strHeadSend += " HTTP/1.0\r\n";
strHeadSend += "Accept: */*\r\n";
strHeadSend += "Accept-Language: en-us\r\n";
strHeadSend += "Host: ";
strHeadSend += host;
strHeadSend += "\r\n\r\n";
//发送请求头
SendString( sock, strHeadSend.c_str() );
// MemBuffer headersBuffer,messageBuffer;
//
// MemBufferCreate(&headersBuffer );
chars = 0;
BOOL done;
done = FALSE;
char buffer[RECV_BUFFER_LEN] = { 0 };
int nPosition = 0;
while(!done)
{
l = recv(sock,buffer + nPosition,1,0);
if(l<0)
done=TRUE;
switch(*(buffer+nPosition))
{
case '\r':
break;
case '\n':
if(chars==0)
done = TRUE;
chars=0;
break;
default:
chars++;
break;
}
nPosition++;
}
//获得状态码
//200 OK 客户端请求成功
//400 Bad Request 客户端有语法错误,不能被服务器所理解
//401 Unauthorized 请求未经授权
//403 Forbidden 服务器收到请求,但是拒绝提供服务
//404 Not Found 请求资源不存在,可能输入了错误的URL
//500 Internal Server Error 服务器发生了不可预期的错误
//503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
CHAR szHttpVer[ 32 ] = { 0 };
INT nStatusCode = 0;
sscanf( buffer, "%s %d", szHttpVer, &nStatusCode );
if( 200 != nStatusCode )
{
if( 403 == nStatusCode || 503 == nStatusCode )
{
}
else
{
return 1;//失败
}
}
//获得文件长度
INT nFileLength = 0;
char* pFindCL = strstr( buffer, "Content-Length:" );
if( pFindCL != NULL )
{
CHAR szTemp[ 32 ] = { 0 };
sscanf( pFindCL, "%s %d", szTemp, &nFileLength );
}
//得到路径
char szDirectory[ MAX_PATH ] = { 0 };
GetCurrentDirectory( MAX_PATH, szDirectory );
std::string strFileName = szDirectory;
strFileName += request;
std::replace( strFileName.begin(), strFileName.end(), '\\', '/' );
//获得原始文件名称
std::string strOrigFileName = strFileName;
// int findPos = strFileName.find_last_of( "/" );
// if( findPos != string::npos )
// {
// strOrigFileName = strFileName.substr( findPos + 1 );
// }
strFileName += ".tmp"; //文件名称修改成一个临时文件名称,下载完毕后还原
FILE* pFile = NULL;
fopen_s(&pFile, strFileName.c_str(), "wb" ); //打开一个文件,写,如果文件存在,则清空
if( !pFile )
{
return 1;
}
INT nRecvedSize = 0; //已经接收的数量
INT nPos = 0; //偏移
while( TRUE )
{
INT nRecv = recv( sock, buffer + nPos, RECV_BUFFER_LEN - nPos, 0 );
if( nRecv > 0 )
{
nRecvedSize += nRecv;
nPos += nRecv;
if( nPos >= RECV_BUFFER_LEN && nRecvedSize < nFileLength )//BUFF满了,但文件没有接受完毕
{
//内容写到文件中
fwrite( buffer, RECV_BUFFER_LEN, 1, pFile );
nPos = 0;
}
else if( nRecvedSize >= nFileLength )//文件接收完毕
{
//文件接收完毕,保存内容
fwrite( buffer, nPos, 1, pFile );
fclose( pFile );
//修改文件名称
rename( strFileName.c_str(), strOrigFileName.c_str() );
break;
}
}
else if( 0 == nRecv )
{
//socket关闭
break;
}
else
{
int nErrCode = WSAGetLastError();
break;
}
}
closesocket(sock);
return 0;
}