您的位置:首页 > 理论基础 > 计算机网络

http 协议获取文件大小

2012-02-15 16:29 337 查看
转自网络

问题:

我要从http://www.traceboard.com/updatedoc/SetPoint.CAB

下载文件SetPoint.CAB

FhSession=InternetOpen("www.traceboard.com",INTERNET_OPEN_TYPE_PRECONFIG, NULL,NULL,0);

FhConnect=InternetConnect(FhSession,"www.traceboard.com",INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);

const char *FAcceptTypes="CAB"; //要下载的文件后缀.CAB

FhRequest=HttpOpenRequest(FhConnect,"GET", CABFile,NULL,RemoteCABFile, &FAcceptTypes,INTERNET_FLAG_RELOAD,0);

HttpSendRequest(FhRequest, NULL, 0, NULL, 0);



DWORD BufLen=sizeof(Buffer);

DWORD dwIndex=0;

bool RetQueryInfo=HttpQueryInfo(FhRequest,HTTP_QUERY_CONTENT_LENGTH, Buffer,&BufLen, &dwIndex);

int FileSize=StrToInt(Buffer);

最后得不到文件大小。。。换文件下载FileSize始终=20

问题出在哪呢?

// HttpSocket.h: interface for the CHttpSocket class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_)
#define AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_

#include <afxinet.h>

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHttpSocket  
{
public:
    CHttpSocket();
    virtual ~CHttpSocket();
    int    GetServerState();//返回服务器状态码 -1表示不成功
    int    GetField(const char* szSession,char *szValue,int nMaxLength);//返回某个域值,-1表示不成功
    int    GetResponseLine(char *pLine,int nMaxLength);//获取返回头的一行
    const char*    GetResponseHeader(int &Length);//获取完整的返回头
    const char *FormatRequestHeader(char *pServer,char *pObject,long &Length,
                        char* pCookie=NULL,char *pReferer=NULL,
                        long nFrom=0,long nTo=0,
                        int nServerType=0);//格式化请求头
    int    GetRequestHeader(char *pHeader,int nMaxLength) const;
    BOOL SendRequest(const char* pRequestHeader = NULL,long Length = 0);    
    BOOL SetTimeout(int nTime,int nType=0);
    long Receive(char* pBuffer,long nMaxLength);
    BOOL Connect(char* szHostName,int nPort=80);
    BOOL Socket();
    BOOL CloseSocket();
protected:    
    char m_requestheader[1024];        //请求头
    char m_ResponseHeader[1024];    //回应头
    int m_port;                        //端口
    char m_ipaddr[256];                //IP地址
    BOOL m_bConnected;
    SOCKET m_s;
    hostent *m_phostent;

    int m_nCurIndex;                //GetResponsLine()函数的游标记录
    BOOL m_bResponsed;                //是否已经取得了返回头
    int m_nResponseHeaderSize;        //回应头的大小
};

#endif // !defined(AFX_HTTPSOCKET_H__F49A8F82_A933_41A8_AF47_68FBCAC4ADA6__INCLUDED_)


// HttpSocket.cpp: implementation of the CHttpSocket class. 
 // 
 ////////////////////////////////////////////////////////////////////// 
  
 #include "stdafx.h" 
 #include "HttpSocket.h" 
  
 #ifdef _DEBUG 
 #undef THIS_FILE 
 static char THIS_FILE[]=__FILE__; 
 #define new DEBUG_NEW 
 #endif 
  
 #define MAXHEADERSIZE 1024 
 ////////////////////////////////////////////////////////////////////// 
 // Construction/Destruction 
 ////////////////////////////////////////////////////////////////////// 
 CHttpSocket::CHttpSocket() 
 { 
 	m_s=NULL; 
 	m_phostent=NULL; 
 	m_port=80; 
 	m_bConnected=FALSE; 
 	for(int i=0;i <256;i++) 
 		m_ipaddr[i]='\0'; 
 	memset(m_requestheader,0,MAXHEADERSIZE); 
 	memset(m_ResponseHeader,0,MAXHEADERSIZE); 
 	m_nCurIndex = 0;		// 
 	m_bResponsed = FALSE; 
 	m_nResponseHeaderSize = -1; 
 } 
  
 CHttpSocket::~CHttpSocket() 
 { 
 	CloseSocket(); 
 } 
  
 BOOL CHttpSocket::Socket() 
 { 
 	if(m_bConnected)return FALSE; 
  
 	struct protoent *ppe;  
 	ppe=getprotobyname("tcp");  
 	 
 	///创建SOCKET对象 
 	m_s=socket(PF_INET,SOCK_STREAM,ppe->p_proto); 
 	if(m_s==INVALID_SOCKET) 
 	{ 
 		TRACE("socket()函数执行失败!\n"); 
 		return FALSE; 
 	} 
  
 	return TRUE; 
  
 } 
  
 BOOL CHttpSocket::Connect(char *szHostName,int nPort) 
 { 
 	if(szHostName==NULL) 
 		return FALSE; 
  
 	///若已经连接,则先关闭 
 	if(m_bConnected) 
 	{ 
 		CloseSocket(); 
 	} 
  
 	///保存端口号 
 	m_port=nPort; 
  
 	///根据主机名获得IP地址 
 	m_phostent=gethostbyname(szHostName); 
 	if(m_phostent==NULL) 
 	{ 
 		TRACE("gethostbyname()函数执行失败!\n"); 
 		return FALSE; 
 	}	 
 	///连接 
 	struct in_addr ip_addr; 
 	memcpy(&ip_addr,m_phostent->h_addr_list[0],4);///h_addr_list[0]里4个字节,每个字节8位 
  
 	struct sockaddr_in destaddr; 
 	memset((void *)&destaddr,0,sizeof(destaddr));  
 	destaddr.sin_family=AF_INET; 
 	destaddr.sin_port=htons(80); 
 	destaddr.sin_addr=ip_addr; 
  
 	///保存主机的IP地址字符串 
 	sprintf(m_ipaddr,"%d.%d.%d.%d", 
 		destaddr.sin_addr.S_un.S_un_b.s_b1, 
 		destaddr.sin_addr.S_un.S_un_b.s_b2, 
 		destaddr.sin_addr.S_un.S_un_b.s_b3, 
 		destaddr.sin_addr.S_un.S_un_b.s_b4); 
  
 	if(connect(m_s,(struct sockaddr*)&destaddr,sizeof(destaddr))!=0) 
 	{ 
 	//	TRACE(NULL,"connect()函数执行失败!","错误",MB_OK); 
 		return FALSE; 
 	} 
 	///设置已经连接的标志 
 	m_bConnected=TRUE; 
 	return TRUE; 
 } 
  
 ///根据请求的相对URL输出HTTP请求头 
 const char *CHttpSocket::FormatRequestHeader(char *pServer,char *pObject, long &Length, 
 									  char *pCookie,char *pReferer,long nFrom, 
 									  long nTo,int nServerType) 
 { 
 	char szPort[10]; 
 	char szTemp[20]; 
 	sprintf(szPort,"%d",m_port); 
 	memset(m_requestheader,'\0',1024); 
  
 	///第1行:方法,请求的路径,版本 
 	strcat(m_requestheader,"GET "); 
 	strcat(m_requestheader,pObject); 
 	strcat(m_requestheader," HTTP/1.1"); 
     strcat(m_requestheader,"\r\n"); 
  
 	///第2行:主机 
     strcat(m_requestheader,"Host:"); 
 	strcat(m_requestheader,pServer); 
     strcat(m_requestheader,"\r\n"); 
  
 	///第3行: 
 	if(pReferer != NULL) 
 	{ 
 		strcat(m_requestheader,"Referer:"); 
 		strcat(m_requestheader,pReferer); 
 		strcat(m_requestheader,"\r\n");		 
 	} 
  
 	///第4行:接收的数据类型 
     strcat(m_requestheader,"Accept:*/*"); 
     strcat(m_requestheader,"\r\n"); 
  
 	///第5行:浏览器类型 
     strcat(m_requestheader,"User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)"); 
     strcat(m_requestheader,"\r\n"); 
  
 	///第6行:连接设置,保持 
 	strcat(m_requestheader,"Connection:Keep-Alive"); 
 	strcat(m_requestheader,"\r\n"); 
  
 	///第7行:Cookie. 
 	if(pCookie != NULL) 
 	{ 
 		strcat(m_requestheader,"Set Cookie:0"); 
 		strcat(m_requestheader,pCookie); 
 		strcat(m_requestheader,"\r\n"); 
 	} 
  
 	///第8行:请求的数据起始字节位置(断点续传的关键) 
 	if(nFrom > 0) 
 	{ 
 		strcat(m_requestheader,"Range: bytes="); 
 		_ltoa(nFrom,szTemp,10); 
 		strcat(m_requestheader,szTemp); 
 		strcat(m_requestheader,"-"); 
 		if(nTo > nFrom) 
 		{ 
 			_ltoa(nTo,szTemp,10); 
 			strcat(m_requestheader,szTemp); 
 		} 
 		strcat(m_requestheader,"\r\n"); 
 	} 
 	 
 	///最后一行:空行 
 	strcat(m_requestheader,"\r\n"); 
  
 	///返回结果 
 	Length=strlen(m_requestheader); 
 	return m_requestheader; 
 } 
  
 ///发送请求头 
 BOOL CHttpSocket::SendRequest(const char *pRequestHeader, long Length) 
 { 
 	if(!m_bConnected)return FALSE; 
  
 	if(pRequestHeader==NULL) 
 		pRequestHeader=m_requestheader; 
 	if(Length==0) 
 		Length=strlen(m_requestheader); 
  
 	if(send(m_s,pRequestHeader,Length,0)==SOCKET_ERROR) 
 	{ 
 		TRACE("send()函数执行失败!\n"); 
 		return FALSE; 
 	} 
 	int nLength; 
 	GetResponseHeader(nLength); 
 	return TRUE; 
 } 
  
 long CHttpSocket::Receive(char* pBuffer,long nMaxLength) 
 { 
 	if(!m_bConnected)return NULL; 
  
 	///接收数据 
 	long nLength; 
 	nLength=recv(m_s,pBuffer,nMaxLength,0); 
 	 
 	if(nLength  <= 0) 
 	{ 
 		//MessageBox(NULL,"recv()函数执行失败!","错误",MB_OK); 
 		CloseSocket(); 
 	} 
 	return nLength; 
 } 
  
 ///关闭套接字 
 BOOL CHttpSocket::CloseSocket() 
 { 
 	if(m_s != NULL) 
 	{ 
 		if(closesocket(m_s)==SOCKET_ERROR) 
 		{ 
 			TRACE("closesocket()函数执行失败!\n"); 
 			return FALSE; 
 		} 
 	} 
 	m_s = NULL; 
 	m_bConnected=FALSE; 
 	return TRUE; 
 } 
  
 int CHttpSocket::GetRequestHeader(char *pHeader, int nMaxLength) const 
 { 
 	int nLength; 
 	if(int(strlen(m_requestheader))>nMaxLength) 
 	{ 
 		nLength=nMaxLength; 
 	} 
 	else 
 	{ 
 		nLength=strlen(m_requestheader); 
 	} 
 	memcpy(pHeader,m_requestheader,nLength); 
 	return nLength; 
 } 
  
 //设置接收或者发送的最长时间 
 BOOL CHttpSocket::SetTimeout(int nTime, int nType) 
 { 
 	if(nType == 0) 
 	{ 
 		nType = SO_RCVTIMEO; 
 	} 
 	else 
 	{ 
 		nType = SO_SNDTIMEO; 
 	} 
  
 	DWORD dwErr; 
     dwErr=setsockopt(m_s,SOL_SOCKET,nType,(char*)&nTime,sizeof(nTime));  
 	if(dwErr) 
 	{ 
 		TRACE("setsockopt()函数执行失败!\n"); 
 		return FALSE; 
 	} 
 	return TRUE; 
 } 
  
 //获取HTTP请求的返回头 
 const char* CHttpSocket::GetResponseHeader(int &nLength) 
 { 
 	if(!m_bResponsed) 
 	{ 
 		char c = 0; 
 		int nIndex = 0; 
 		BOOL bEndResponse = FALSE; 
 		while(!bEndResponse && nIndex  < MAXHEADERSIZE) 
 		{ 
 			recv(m_s,&c,1,0); 
 			m_ResponseHeader[nIndex++] = c; 
 			if(nIndex >= 4) 
 			{ 
 				if(m_ResponseHeader[nIndex - 4] == '\r' && m_ResponseHeader[nIndex - 3] == '\n' 
 					&& m_ResponseHeader[nIndex - 2] == '\r' && m_ResponseHeader[nIndex - 1] == '\n') 
 				bEndResponse = TRUE; 
 			} 
 		} 
 		m_nResponseHeaderSize = nIndex; 
 		m_bResponsed = TRUE; 
 	} 
 	 
 	nLength = m_nResponseHeaderSize; 
 	return m_ResponseHeader; 
 } 
  
 //返回HTTP响应头中的一行. 
 int CHttpSocket::GetResponseLine(char *pLine, int nMaxLength) 
 { 
 	if(m_nCurIndex >= m_nResponseHeaderSize) 
 	{ 
 		m_nCurIndex = 0; 
 		return -1; 
 	} 
  
 	int nIndex = 0; 
 	char c = 0; 
 	do  
 	{ 
 		c = m_ResponseHeader[m_nCurIndex++]; 
 		pLine[nIndex++] = c; 
 	} while(c != '\n' && m_nCurIndex  < m_nResponseHeaderSize && nIndex  < nMaxLength); 
 	 
 	return nIndex; 
 } 
  
 int CHttpSocket::GetField(const char *szSession, char *szValue, int nMaxLength) 
 { 
 	//取得某个域值 
 	if(!m_bResponsed) return -1; 
 	 
 	CString strRespons; 
 	strRespons = m_ResponseHeader; 
 	int nPos = -1; 
 	nPos = strRespons.Find(szSession,0); 
 	if(nPos != -1) 
 	{ 
 		nPos += strlen(szSession); 
 		nPos += 2; 
 		int nCr = strRespons.Find("\r\n",nPos); 
 		CString strValue = strRespons.Mid(nPos,nCr - nPos); 
 		strcpy(szValue,strValue); 
 		return (nCr - nPos); 
 	} 
 	else 
 	{ 
 		return -1; 
 	} 
 } 
  
 int CHttpSocket::GetServerState() 
 { 
 	//若没有取得响应头,返回失败 
 	if(!m_bResponsed) return -1; 
 	 
 	char szState[3]; 
 	szState[0] = m_ResponseHeader[9]; 
 	szState[1] = m_ResponseHeader[10]; 
 	szState[2] = m_ResponseHeader[11]; 
  
 	return atoi(szState); 
 }


//下载子线程
DWORD WINAPI DownLoadIIS(LPVOID lParam)
{
    DOWNLOADIIS_INFO *pIIS = (DOWNLOADIIS_INFO *)lParam;

    if(pIIS->pAttrib->bDownload || pIIS->pAttrib->sDownloadAddr =="")
    {
        delete pIIS;
        return -1;
    }
    
    char szPath[256] = "\0";
    GetCurrentDirectory(256,szPath);
    strcat(szPath,"\\Archive\\");
    char strFilePath[256] = "\0";
    wsprintf(strFilePath,"%s%d.rar",szPath,pIIS->nIndex);

    CHttpSocket HttpSocket;
    CString strServer,strObject;
    unsigned short nPort;
    DWORD dwServiceType;
    long nLength;
    const char *pRequestHeader = NULL;
    AfxParseURL(pIIS->pAttrib->sDownloadAddr,dwServiceType,strServer,strObject,nPort);
    
    pRequestHeader = HttpSocket.FormatRequestHeader((LPTSTR)(LPCTSTR)strServer,(LPTSTR)(LPCTSTR)strObject,nLength);    
    
    
    if(!HttpSocket.Socket())
    {
        TRACE("创建服务器连接出错!\n");
        delete pIIS;
        return -1;
    }
    
    HttpSocket.SetTimeout(16000,0);
    
    if(!HttpSocket.Connect((LPTSTR)(LPCTSTR)strServer,nPort))
    {
        TRACE("连接服务器出错\n");
        delete pIIS;
        return -1;
    }
    
    if(!HttpSocket.SendRequest())
    {
        TRACE("发送请求出错\n");
        delete pIIS;
        return -1;
    }
    
    
    int nLineSize = 0;
    char szValue[30];
    HttpSocket.GetField("Content-Length",szValue,30);
    int nSvrState = HttpSocket.GetServerState();
    
    //服务器状态
    if(nSvrState == 404)
    {
        delete pIIS;
        return -1;
    }
    
    int nFileSize = atoi(szValue);//URL文件的长度
    int nCompletedSize = 0;
    CFile File;
    File.Open(strFilePath,CFile::modeCreate | CFile::modeWrite);
    char pData[1024];
    int nReceSize = 0;
    DWORD dwStartTime,dwEndTime;
    while(nCompletedSize < nFileSize)
    {
        dwStartTime = GetTickCount();
        nReceSize = HttpSocket.Receive(pData,1024);
        if(nReceSize == 0)
        {
            TRACE("服务器已经关闭连接\n");
            delete pIIS;
            return -1;
        }
        if(nReceSize == -1)
        {
            TRACE("接收数据超时.\n");
            delete pIIS;
            return -1;
        }
        dwEndTime = GetTickCount();
        File.Write(pData,nReceSize);
        nCompletedSize += nReceSize;
    }
    File.Close();
////////////////////////////////////////////////////////////////////

其他参考:

FhRequest=HttpOpenRequest(FhConnect, "GET", "/updatedoc/SetPoint.CAB", NULL, NULL, (const char**)"*/*\0",INTERNET_FLAG_RELOAD,0);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: