⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request.cpp

📁 离线的RSS阅读器
💻 CPP
字号:
// Request.cpp: implementation of the Request class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Request.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CRequest::CRequest()
{

}

CRequest::~CRequest()
{

}


//*******************************************************************************************************
//MemBufferCreate: 
//	为传入的MemBuffer结构体指针分配初始内存
//  该缓冲区的大小可以根据需要调整
//*******************************************************************************************************
void CRequest::MemBufferCreate(MemBuffer *b)
{
    b->size = MEM_BUFFER_SIZE;
    b->buffer = (char*)malloc( b->size );
    b->position = b->buffer;
}

//*******************************************************************************************************
// MemBufferGrow:  
//	将传入的MemBuffer结构体的内存缓存区扩大一倍
//*******************************************************************************************************
void CRequest::MemBufferGrow(MemBuffer *b)
{
    size_t sz;
    sz = b->position - b->buffer;			// 记录当前位置与缓冲区头的偏移
    b->size = b->size *2;
    b->buffer =(char *) realloc(b->buffer,b->size);
    b->position = b->buffer + sz;	
}

//*******************************************************************************************************
// MemBufferAddByte: 
//	向缓冲区中添加一个字符。如果需要扩容,则自动扩容
//*******************************************************************************************************
void CRequest::MemBufferAddByte(MemBuffer *b,char byt)
{
    if( (size_t)(b->position-b->buffer) >= b->size )
        MemBufferGrow(b);

    *(b->position++) = byt;
}

//*******************************************************************************************************
// MemBufferAddBuffer:
//	向缓冲区添加size个字节,必要时自动扩容
//*******************************************************************************************************
void CRequest::MemBufferAddBuffer(MemBuffer *b,
                    char *buffer, size_t size)
{
    while( ((size_t)(b->position-b->buffer)+size) >= b->size )
        MemBufferGrow(b);

    memcpy(b->position,buffer,size);
    b->position += size;
}

//*******************************************************************************************************
// GetHostAddress: 
//	指定主机名,如(www.microsoft.com),返回其IP地址
//*******************************************************************************************************
DWORD CRequest::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: 
//	发送一个字符串命令
//*******************************************************************************************************
void CRequest::SendString(SOCKET sock,LPCSTR str)
{
    send(sock,str,strlen(str),0);
}

//*******************************************************************************************************
// ValidHostChar: 
//	验证有效的主机名
//*******************************************************************************************************
BOOL CRequest::ValidHostChar(char ch)
{
    return( isalpha(ch) || isdigit(ch)
        || ch=='-' || ch=='.' || ch==':' );
}


//*******************************************************************************************************
// ParseURL: 
//	解析一个URL。 例如:http://www.microsoft.com:80/index.htm
//	解析结果:protocol: http
//				  port: 80
//                host: www.microsoft.com
//             request: index.htm
//*******************************************************************************************************
void CRequest::ParseURL(LPCSTR 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);
    strupr(work);

    ptr = strchr(work,':');							// 通过':'来查找protocol
    if(ptr != NULL)
    {
        *(ptr++) = 0;								// 将':'替换为'\0'
        lstrcpyn(protocol,work,lprotocol);			// 取得protocol
    }
    else											// 如果url不包含http:
    {
        lstrcpyn(protocol,"HTTP",lprotocol);
        ptr = work;
    }

    if( (*ptr == '/') && (*(ptr+1) == '/') )		// 跳过':'后的'//' (如果有)
        ptr+=2;

    ptr2 = ptr;										
    while( ValidHostChar(*ptr2) && *ptr2 )			// 如果url中碰到任何一个无效主机名字符,那么终止,仅取有效字符
        ptr2++;

    *ptr2=0;										// 碰到'/'或其它无效主机名字符,结束主机名
    lstrcpyn(host,ptr,lhost);
    lstrcpyn(request,url + (ptr2-work),lrequest);	// 将主机名以后的部分放入request中

    ptr = strchr(host,':');							// 查找端口号(如果有)
    if(ptr!=NULL)
    {
        *ptr=0;
        *port = atoi(ptr+1);
    }

    free(work);
}

//*******************************************************************************************************
// SendHTTP: 
//	url				- GET/POST 的URL全路径
//	headerSend		- 送到服务器的请求头
//	post			- 如果是POST, 则包含提交到服务器的字段信息;如果是GET则为NULL
//	postLength		- 如果是POST,则指明提交到服务器的字段的字节长度;如果是GET,则为0
//	req				- 输出参数,存放从http request和response的header和body信息
//*******************************************************************************************************
BOOL CRequest::SendHTTP(LPCSTR url,char *post,DWORD postLength,HTTPRequest *req)
{
    WSADATA			WsaData;
    SOCKADDR_IN		sin;
    SOCKET			sock;
	const int		BUFFER_SIZE = 512;
    char			buffer[BUFFER_SIZE+1];
    char			protocol[20],host[256],request[1024];
    int				l,port,chars,err;
    MemBuffer		headersBuffer,messageBuffer;
	char			headerSend[1024];								// 记录已发送到服务器的请求头
    BOOL			done;

    ParseURL(url,protocol,sizeof(protocol),host,sizeof(host),		// 解析URL
        request,sizeof(request),&port);
    if(strcmp(protocol,"HTTP"))
        return FALSE;

    err = WSAStartup (0x0101, &WsaData);							// 初始化
    if(err!=0)
        return FALSE;

    sock = socket (AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET)
        return FALSE;

    
    sin.sin_family = AF_INET;										
    sin.sin_port = htons( (unsigned short)port );
    sin.sin_addr.s_addr = GetHostAddress(host);

    if( connect (sock,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) ) )		// 连接到远程服务器
	{
        return FALSE;
	}

    if( !*request )
        lstrcpyn(request,"/",sizeof(request));						// 如果没有子路径,则默认为'/';

    if( post == NULL )
	{
        SendString(sock,"GET ");
		strcpy(headerSend, "GET ");
	}
    else 
	{
		SendString(sock,"POST ");
		strcpy(headerSend, "POST ");
	}

    SendString(sock,request);
	strcat(headerSend, request);									// 附加子路径

    SendString(sock," HTTP/1.0\r\n");
	strcat(headerSend, " HTTP/1.0\r\n");							// 附加协议

    SendString(sock,"Accept: text/xml, image/gif, image/x-xbitmap,"
        " image/jpeg, image/pjpeg, application/vnd.ms-excel,"
        " application/msword, application/vnd.ms-powerpoint,"
        " */*\r\n");
	strcat(headerSend, "Accept: image/gif, image/x-xbitmap,"
        " image/jpeg, image/pjpeg, application/vnd.ms-excel,"
        " application/msword, application/vnd.ms-powerpoint,"
        " */*\r\n");												// 附加请求头

    SendString(sock,"Accept-Language: en-us\r\n");
	strcat(headerSend, "Accept-Language: en-us\r\n");

    SendString(sock,"Accept-Encoding: gzip, deflate\r\n");			
	strcat(headerSend, "Accept-Encoding: gzip, deflate\r\n");		// 附加协议头

    SendString(sock,"User-Agent: Mozilla/4.0\r\n");
	strcat(headerSend, "User-Agent: Mozilla/4.0\r\n");				// 附加协议头

    if(postLength)													// 如果是post, 需要送出请求字段的长度
    {
        wsprintf(buffer,"Content-Length: %ld\r\n",postLength);
        SendString(sock,buffer);
		strcat(headerSend, buffer);									
    }
	
    SendString(sock,"Host: ");
	strcat(headerSend, "Host: ");
    SendString(sock,host);
	strcat(headerSend, host);										// 送出主机信息

    SendString(sock,"\r\n");
	strcat(headerSend, "\r\n");

    if (postLength)
	{
		SendString(sock, "Content-Type: application/x-www-form-urlencoded\r\n");
		strcat(headerSend, "Content-Type: application/x-www-form-urlencoded\r\n");
	}
    
    SendString(sock,"\r\n");								
	strcat(headerSend, "\r\n");										// http头信息发送完毕

    if( (post!=NULL) && postLength )								// 如果是POST, 送出表单字段
	{
        send(sock,(const char*)post,postLength,0);
		post[postLength]	= '\0';
		strcat(headerSend, (const char*)post);
	}
    
	req->headerSend		= (char*) malloc( sizeof(char*) * strlen(headerSend));
	strcpy(req->headerSend, (char*) headerSend );

    MemBufferCreate(&headersBuffer );
    chars = 0;
    done = FALSE;

    while(!done)													// 接收服务器响应头信息
    {
        l = recv(sock,buffer,1,0);
        if(l<0)
            done=TRUE;

        switch(*buffer)
        {
            case '\r':
                break;
            case '\n':												// 头信息将以空行结束
                if(chars==0)
                    done = TRUE;
                chars=0;
                break;
            default:
                chars++;
                break;
        }

        MemBufferAddByte(&headersBuffer,*buffer);
    }

    req->headerReceive	= (char*)headersBuffer.buffer;
    *(headersBuffer.position) = 0;

    MemBufferCreate(&messageBuffer);	
    do																// 接收从服务器响应的body
    {
        l = recv(sock,buffer,BUFFER_SIZE,0);
        if(l<0)
            break;
		//buffer[l] = '\0';
        MemBufferAddBuffer(&messageBuffer, buffer, l);
    } while(l>0);
	*messageBuffer.position = '\0';
	req->message = messageBuffer.buffer;
    req->messageLength = (messageBuffer.position - messageBuffer.buffer);

    closesocket(sock);											
    return TRUE;
}


//*******************************************************************************************************
// SendRequest
//	IsPost				指示是GET还是POST方式
//  url					要访问的全路径
//  psHeaderSender		输出参数,存放所有发送到服务器的http request head信息
//  psHeaderReceive		输出参数,存放从服务器返回的http response head信息
//  psMessage			输出参数,存放从服务器返回的http response body信息
//*******************************************************************************************************
//void Request::SendRequest(bool IsPost, LPCSTR url, char *pszHeaderSend, char *pszHeaderReceive, char *pszMessage)
BOOL CRequest::SendRequest(bool IsPost, LPCSTR url, const char* psHeaderSend, HTTPRequest* req)
{
	//HTTPRequest			req;
    int					i,j;
	BOOL				ret;
    LPSTR				buffer;

    req->headerSend = NULL;
	req->headerReceive = NULL;
    req->message	= NULL;

	if(IsPost)
    {													
		i = strlen(psHeaderSend);
		buffer = (char*) malloc(i+1);
		strcpy(buffer, psHeaderSend);
		ret	= SendHTTP(	url, (char*)buffer, i, req);
        free(buffer);
    }
    else													// 以GET方式送出			
        ret = SendHTTP(url,NULL,0,req);

	/*if(ret)											
	{
		psHeaderSend = req.headerSend;
		psHeaderReceive	= req.headerReceive;
		psMessage = req.message;

		free(req.headerSend);
		free(req.headerReceive);
        free(req.message);		
    }*/

	return ret;
}

void CRequest::MemBufferFree(HTTPRequest* req)
{
	if (req != NULL)
	{
		free(req->headerSend);
		free(req->headerReceive);
        free(req->message);	
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -