C++使用WinInet获取网络JSON响应的代码修正方案
核心错误说明
你的代码无法正常请求的核心原因是WinINet系列API参数传参错误,同时存在响应读取不全、资源泄漏、请求协议不匹配的问题:
InternetConnect第二个参数仅接收服务器域名/IP,不能传入完整URL,传入全路径会导致无法连接到正确服务HttpOpenRequest第三个参数接收请求的资源相对路径,传入完整URL会导致请求路径非法- 未做任何API调用返回值校验,请求出错时无法定位问题,还会执行后续无效逻辑
- 仅调用一次
InternetQueryDataAvailable+单次读取无法拿到完整响应,数据长度不准时会出现JSON截断 - 动态申请的缓冲区未释放,存在内存泄漏
- 使用HTTP协议请求时,当前ip-api接口默认会跳转HTTPS,会导致请求失败
- GET请求不需要添加
Content-Type: application/json头,多余头可能触发服务端拦截
前置依赖
编译前请在代码开头引入WinINet相关依赖:
#include <windows.h> #include <wininet.h> #include <string> #pragma comment(lib, "wininet.lib") using namespace std;
修正后代码
string GetLocation() { DWORD wrt = 0; LPCWSTR userAgent = L"SimpleLocationClient"; string response; // 按WinINet要求拆分服务器地址和请求路径 LPCWSTR server = L"ip-api.com"; LPCWSTR path = L"/json/168.197.155.244"; // 初始化网络会话 HINTERNET hSession = InternetOpen(userAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hSession) return ""; // 建立HTTPS连接,使用默认443端口 HINTERNET hConnect = InternetConnect(hSession, server, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConnect) { InternetCloseHandle(hSession); return ""; } // 创建GET请求,添加HTTPS安全标志 HINTERNET hRequest = HttpOpenRequest(hConnect, L"GET", path, NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD, 0); if (!hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hSession); return ""; } // 发送请求 if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) { InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); return ""; } // 循环读取完整响应,避免截断 const int BUF_SIZE = 4096; char buf[BUF_SIZE]; while (true) { memset(buf, 0, BUF_SIZE); BOOL readRes = InternetReadFile(hRequest, buf, BUF_SIZE - 1, &wrt); if (!readRes || wrt == 0) break; response.append(buf, wrt); } // 按顺序关闭所有句柄释放资源 InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); return response; }
关键修改点
- 拆分服务器地址和请求路径,匹配WinINet的参数要求
- 切换为HTTPS协议,添加对应安全标志和默认端口,避免跳转拦截
- 移除GET请求不需要的多余请求头
- 增加每一步API调用的返回值校验,出错时提前退出并释放已申请资源
- 用固定缓冲区循环读取响应,保证能拿到完整JSON数据
- 去掉无意义的动态内存申请,避免内存泄漏
- 调整句柄关闭顺序,所有异常分支都能正确释放资源
内容的提问来源于stack exchange,提问作者Antony Lucas
相关产品推荐
相关产品推荐

