📄 request.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 + -