1.1 背景
前一段时间,客户机器上的产品一直登陆不上,说是以前一直可以用,突然就用不了了.登录时候会一直报:登录超时.而且,现场的同事将产品卸载重装也还是一样.故事就此拉开了序幕.
1.2 代码的查找
登录是通过HTTP_POST协议来实现的,大致的代码如下:
m_pConnection = m_pSession->GetHttpConnection(strServer,
dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_CONNECT : SECURE_CONNECT,
nPort);
m_pFile = m_pConnection->OpenRequest(strMethod, strObject,
NULL, 1, NULL, NULL,
(dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_REQUEST : SECURE_REQUEST));
m_pFile->AddRequestHeaders("Accept: *,*/*");
m_pFile->AddRequestHeaders("Accept-Language: zh-cn");
m_pFile->AddRequestHeaders("Content-Type: application/x-www-form-urlencoded");
m_pFile->AddRequestHeaders("Accept-Encoding: gzip, deflate");
BOOL bSend=m_pFile->SendRequest(NULL, 0, (LPVOID)(LPCTSTR)strPostData, strPostData == NULL ? 0 : _tcslen(strPostData));
char szChars[BUFFER_SIZE + 1] = {0};
CString strRawResponse = "";
UINT nReaded = 0;
while ((nReaded = m_pFile->Read((void*)szChars, BUFFER_SIZE)) > 0)
{
szChars[nReaded] = '\0';
strRawResponse += szChars;
memset(szChars, 0, BUFFER_SIZE + 1);
}
int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, strRawResponse.GetBuffer(0), -1, NULL, 0);
WCHAR *pUnicode = new WCHAR[unicodeLen + 1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8,0,strRawResponse.GetBuffer(0),-1, pUnicode,unicodeLen);
CString cs(pUnicode);
delete []pUnicode;
pUnicode = NULL;
strResponse = cs;
Clear();
}
catch (CInternetException* e)
{
Clear();
DWORD dwErrorCode = e->m_dwError;
char ErrMsg[MAX_PATH]={0};
e->GetErrorMessage(ErrMsg,MAX_PATH);
e->Delete();
BOOL bSend=m_pFile->SendRequest(NULL, 0, (LPVOID)(LPCTSTR)strPostData, strPostData == NULL ? 0 : _tcslen(strPostData));通过打印出catch 到的 CInternetException, 其中的 dwError==2. 即 ERROR_FILE_NOT_FOUND. 然后也通过打印定位 , 发现是在执行
BOOL bSend=m_pFile->SendRequest(NULL, 0, (LPVOID)(LPCTSTR)strPostData, strPostData == NULL ? 0 : _tcslen(strPostData));
这一句代码的时候抛出了异常.
这就有点尴尬了,我查MSDN了,只叫我去关注这个抛出的异常,但是这个异常却是”文件未找到”(ERROR_FILE_NOT_FOUND).
1.3 抓包查找
叫现场的同事抓包给我,我发现并没有http的包,而且连tcp的包也没有,更不用谈什么三次握手啥的了
1.4 网上查找
网上百度,google查半天,没有查到相关的任何错误,只看到有一个哥们碰到和我一样的问题,最后是重装系统解决的...
1.5 查看未包装的函数
跟踪CHttpFile::SendRequest的代码,发现其中调用的是HttpSendRequest,而且在HttpSendRequest返回为false的时候会抛出异常.去MSDN中查看关于HttpSendRequest的说明,在Remarks中发现了很重要的一行:
In offline mode, HttpSendRequest returns ERROR_FILE_NOT_FOUND if the resource is not found in the Internet cache.
翻译过来意思是:在离线模式下,如果在Internet缓存中没有发现资源,HttpSendRequest将返回ERROR_FILE_NOT_FOUND.
现在关键是,什么是离线模式呢...
前面的建立HTTP连接什么的也没有发现可以设置什么离线模式的啊.
1.6 再次网上查找
通过前面获得的信息,在网上继续查找,终于在stackflow上面发现了一个歪果仁回的一端英文,原文我是不记得了,大意如下:
使用HttpSendRequest时候,如果IE设置为离线模式,那么HttpSendRequest是可能返回ERROR_FILE_NOT_FOUND.所以要解决这个问题可以将IE设置为在线模式.步骤:打开IE,找到文件菜单->取消掉脱机工作.(如果你没有找到文件菜单,请按ALT按钮).
不得不说,歪果仁兄还是很贴心的,还告诉你怎么呼出文件菜单...
而且,这也正是这次问题的症结所在.
1.7 小结
HttpSendRequest竟然会因为IE设置脱机工作而出现这样的问题...
我也是很醉...
不过Microsoft在MSDN中竟然也还将这个写下了,佩服!