web服务器为Aapache(运行在linux上)扩展模块(参看这里),将收到来自客户端的POST请求文本写到某个目录中,客户端发送代码如下(不完整):
strcpy(szURL, "http://www.xxx.com") // xxx 仅仅为了说明问题 if (!::InternetCheckConnection(szURL, FLAG_ICC_FORCE_CONNECTION, 0)) return FALSE; TCHAR szModuleFile[MAX_PATH] = {0}; ::GetModuleFileName(NULL, szModuleFile, MAX_PATH); LPCTSTR lpPath = ::PathFindFileName(szModuleFile); HINTERNET hOpen = ::InternetOpen(lpPath, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0); if (NULL == hOpen) return FALSE; HINTERNET hConnect = ::InternetConnect(hOpen, lpDomain, dwPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (NULL == hConnect) goto FUN_END2; LPCTSTR szAccept[] = {_T("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"), NULL}; DWORD dwFlag = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION; HINTERNET hOpenRequest = ::HttpOpenRequest(hConnect, _T("POST"), _T("my_app"), _T("HTTP/1.1"), szURL, szAccept, dwFlag, 0); // my_app是apache扩展C++模块. if (NULL == hOpenRequest) goto FUN_END1; BOOL bRet = FALSE; TCHAR headerContentLength[64]; _stprintf(headerContentLength, _T("Content-Length: %d\r\n\r\n"), nLen); // 这个语句向http://www.xxx.com/my_app发送数据. bRet = ::HttpSendRequest(hOpenRequest, headerContentLength, _tcslen(headerContentLength), utf8PostData, nLen); DWORD dwErr = ::GetLastError(); if (!bRet) goto FUN_END1; TCHAR szBuff[BUF_LEN_1024] = {0}; DWORD dwBuffSize = BUF_LEN_1024*sizeof(szBuff)-2; bRet = ::HttpQueryInfo(hOpenRequest, HTTP_QUERY_STATUS_CODE, (LPVOID)szBuff, &dwBuffSize, NULL); //Reference to http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html int nStatusCode = _tstoi(szBuff); //if (nStatusCode<200 || 206<nStatusCode) if (200 != nStatusCode) bRet = FALSE; ......
在调试过程中发现,HttpSendRequest总是返回FALSE,错误码为12152(MSDN定义,ERROR_HTTP_INVALID_SERVER_RESPONSE,The server response could not be parsed).经过抓包可知,网络正常,3次握手,4次分手都正常,说明apache确实收到了这份数据,通过浏览器访问http://www.xxx.com/my_app也正常.
有不少网友说该错误可能发生在客户端或者系统,例如杀毒软件,网络异常等等,现这里不是这种问题,经过调查发现,错误竟然出在服务端读写权限上.扩展模块my_app会将收到的数据写到目录log,但log的权限开始是"drwxr-xr-x.",后来修改了权限(chmod ugo+w log)为"drwxrwxrwx."竟然可以了.
从这个错误可以看出,当apache不能处理某个http请求时,不会将相应的数据传递给C++扩展模块,而是返回错误(12152)给发送程序.