微端下載用到的代碼

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; 




發佈了17 篇原創文章 · 獲贊 6 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章