18,356
社区成员
发帖
与我相关
我的任务
分享
bool myCInternet::HttpRequst(string Host,
string &strBody,
string &Heard,
UINT uPort /* = 80 */,
string Context,
string Methohd /* ="GET" */,
string ObjectName /* = "" */,
char* Addheard[],
int NumHeard,
string ProxName,
string PassProxName)
{
LPCTSTR lpszAgent = "WinInetGet/0.1";
HINTERNET hInternet = InternetOpen( lpszAgent,
ProxName.length()?INTERNET_OPEN_TYPE_PROXY:INTERNET_OPEN_TYPE_PRECONFIG,
ProxName.length()?ProxName.c_str():NULL,
PassProxName.length()?PassProxName.c_str():NULL,
0);
if(NULL == hInternet)
return false;
LPCTSTR lpszServerName = (char*)Host.c_str();
INTERNET_PORT nServerPort = uPort; //
LPCTSTR lpszUserName = NULL; //无登录用户名
LPCTSTR lpszPassword = NULL; //无登录密码
DWORD dwConnectFlags = 0;
DWORD dwConnectContext = 0;
HINTERNET hConnect = InternetConnect(hInternet,
lpszServerName,
nServerPort,
lpszUserName,
lpszPassword,
INTERNET_SERVICE_HTTP,
dwConnectFlags,
dwConnectContext);
LPCTSTR lpszVerb = (char*)Methohd.c_str();
LPCTSTR lpszVersion = NULL; // 默认.
LPCTSTR lpszReferrer = NULL; // 没有引用页
LPCTSTR *lplpszAcceptTypes = NULL; // Accpet所有类型.
DWORD dwOpenRequestFlags = INTERNET_FLAG_RELOAD;
if(uPort == 443)
{
dwOpenRequestFlags |= INTERNET_FLAG_SECURE;
}
DWORD dwOpenRequestContext = 0;
//初始化Request
HINTERNET hRequest = HttpOpenRequest(hConnect,
lpszVerb,
ObjectName.c_str(),
lpszVersion,
lpszReferrer,
lplpszAcceptTypes,
dwOpenRequestFlags,
dwOpenRequestContext);
//添加Heard
if(0 != NumHeard)
{
for(int i = 0;i < NumHeard; i++)
{
HttpAddRequestHeaders(hRequest,
Addheard[i],
strlen(Addheard[i]),
HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
}
}
//发送Request
BOOL bResult = HttpSendRequest(hRequest, NULL, 0, (char*)Context.c_str(), Context.length());
//失败
if (!bResult)
{
fprintf(stderr,
"HttpSendRequest failed, error = %d (0x%x)\n",
GetLastError(),
GetLastError());
return false;
}
//获得HTTP Response Header信息
DWORD dwInfoLevel = HTTP_QUERY_RAW_HEADERS_CRLF;
DWORD dwInfoBufferLength = 2048;
BYTE *pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength);
while (!HttpQueryInfo(hRequest, dwInfoLevel, pInfoBuffer, &dwInfoBufferLength, NULL))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
free(pInfoBuffer);
pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength);
}
else
{
fprintf(stderr,
"HttpQueryInfo failed, error = %d (0x%x)\n",
GetLastError(),
GetLastError());
return false;
}
}
pInfoBuffer[dwInfoBufferLength] = '\0';
Heard = (char*)pInfoBuffer;
free(pInfoBuffer);
//获得http body
DWORD dwBytesAvailable;
//puts("检测HTML Body");
while (InternetQueryDataAvailable(hRequest, &dwBytesAvailable, 0, 0))
{
BYTE *pMessageBody = (BYTE *)malloc(dwBytesAvailable+1);
DWORD dwBytesRead;
//puts("读Body");
BOOL bResult = InternetReadFile(hRequest,
pMessageBody,
dwBytesAvailable,
&dwBytesRead);
if (!bResult)
{
fprintf(stderr,
"InternetReadFile failed, error = %d (0x%x)\n",
GetLastError(),
GetLastError());
free(pMessageBody);
return false;
}
if (dwBytesRead == 0)
{
free(pMessageBody);
pMessageBody = NULL;
break; // End of File.
}
string str;
pMessageBody[dwBytesRead] = '\0';
strBody += (char*)pMessageBody;
//puts("进行转码");
/*Utf8ToMb((char*)pMessageBody,strlen((char*)pMessageBody),str);
//printf("%s", pMessageBody);
//printf("%s", str.c_str());
//要进行转码
//puts("转码完成");
Body += str;
//puts("释放内存");*/
free(pMessageBody);
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return true;
}
所以, ProxName 和 PassProxName 是在调用 HttpRequst 函数时由实参给它们完成初始化的。
而调用 HttpRequst 函数的代码如下:
bool isOk = HttpRequst(Host,Heard,0,80,Context,Methohd,ObjectName,AddHeard,1);
你自己去把函数调用语句和函数定义的头部 一 一 对 应 就可以知道 ProxName 和 PassProxName 的值了。
至于下面这一句:
string PostData = "staticpage=http%3A%2F%2Fwww.baidu.com%2Fcache%2Fuser%2Fhtml%2Fv3Jump.html&charset=utf-8&tpl=mn&apiver=v3&tt=1396272819531&codestring=&safeflg=0&u=http%3A%2F%2Fwww.baidu.com%2F&isPhone=&quick_user=0&logintype=dialogLogin&logLoginType=pc_loginDialog&loginmerge=true&splogin=rate&verifycode=&callback=parent.bd__pcbs__8wed6t&token=";
它是网页向百度的服务器提交数据时所应该遵循的格式,分析后面的代码可以知道,这个 PostData 中保存的就是需要提交给服务器的数据,在将 username 和 password 连接到 PostData 末尾之后,就调用 HttpRequst 函数将它提交上去了。
PS:这个代码不像是 MFC 熟手所为,我看到其中有多处不合理之处,代码格式也比较混乱。
HINTERNET InternetOpen(
_In_ LPCTSTR lpszAgent,
_In_ DWORD dwAccessType,
_In_ LPCTSTR lpszProxyName,
_In_ LPCTSTR lpszProxyBypass,
_In_ DWORD dwFlags
);
lpszAgent参数指向一个由 '\0' 结尾的字符串缓冲区,该字符串指定了调用WinInet函数的应用程序或实体的名称,并且使用它来充当 HTTP 通信中的 UserAgent 字段 (MSDN原文解释:This name is used as the user agent in the HTTP protocol) 。 UserAgent 即用户代理,是一种对数据打包、创造分组头,以及编址、传递消息的部件,它的信息包括硬件平台、系统软件、应用软件和用户个人偏好等。用浏览器浏览网页时,浏览器会发送 UserAgent 信息到网站服务器,服务器可以根据 UserAgent 识别用户的操作系统及版本,浏览器及版本,然后判断用户浏览器可以支持的功能,从而返回给浏览器不同的代码,但这种差异一般会很小,甚至没有,所以我们很难会觉察到它的存在。但有时候还是有用的,举个例子,有时候我们想在电脑上访问手机版(wap版)的网页,这时候我们可以手动修改浏览器的 UserAgent 信息,让服务器以为我们是用移动设备在访问网页,从而到达我们的目的。
再来说说你的这段代码:
/*
这里你的 ProxName 和 PassProxName 都是 string 类型的变量。调用此函数时,如果 ProxName 的
长度(即其中字符的个数)不为0,那么传入的第二个参数就是 INTERNET_OPEN_TYPE_PROXY ,第三个
参数就是 ProxName.c_str() ,也就是以 ProxName 调用 string 的成员函数 c_str() 返回一个以 null
终止的 c 字符串;而如果 ProxName 的长度为0,那么第二个参数就是 INTERNET_OPEN_TYPE_PRECONFIG ,
第三个参数为 NULL 。第四个参数取决于 PassProxName 的长度,若为0,那么它将是 PassProxName.c_str(),
否则它就是 NULL 。
*/
InternetOpen( lpszAgent,
ProxName.length()?INTERNET_OPEN_TYPE_PROXY:INTERNET_OPEN_TYPE_PRECONFIG,
ProxName.length()?ProxName.c_str():NULL,
PassProxName.length()?PassProxName.c_str():NULL,
0 );
void func()
{
string str = "abcdefg";
int len = str.length();
cout<<"len: "<<len<<endl;
char ch[50];
strcpy(ch,str.c_str());
cout<<ch<<endl;
//len为7 ch为abcdefg
}