├── WinHttpClient.opensdf ├── README.md ├── WinHttpClient.sln └── WinHttpClient ├── Test.c ├── winhttpclient.h ├── WinHttpClient.vcxproj.filters ├── WinHttpClient.vcxproj └── winhttpclient.c /WinHttpClient.opensdf: -------------------------------------------------------------------------------- 1 | jeanphornJEANPHORN-PC -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Winhttpclient-c 2 | Winhttpclient is an interface which packaged with WinHTTP API written in c. And thanks Brian Lyttle a lot. 3 | 4 | the main interface: 5 | int SendHttpRequest(const wchar_t *verb, wchar_t *url, unsigned char *sendbuf,int sendbuflen, char *output,BOOL proxyFlah); 6 | 7 | verb: GET or POST 8 | url : http and https are both supported. 9 | output: the responsed data from server is stored in output. 10 | proxyFlag: Sending message with proxy or not. 11 | -------------------------------------------------------------------------------- /WinHttpClient.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinHttpClient", "WinHttpClient\WinHttpClient.vcxproj", "{C7A72068-3338-43D2-A6D0-C24FAFE843B0}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C7A72068-3338-43D2-A6D0-C24FAFE843B0}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {C7A72068-3338-43D2-A6D0-C24FAFE843B0}.Debug|Win32.Build.0 = Debug|Win32 14 | {C7A72068-3338-43D2-A6D0-C24FAFE843B0}.Release|Win32.ActiveCfg = Release|Win32 15 | {C7A72068-3338-43D2-A6D0-C24FAFE843B0}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /WinHttpClient/Test.c: -------------------------------------------------------------------------------- 1 | #include "winhttpclient.h" 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | 8 | wchar_t *pszServer = L"http://192.168.1.33/jsbin/server.php"; 9 | wchar_t *server2 = L"http://192.168.1.33/test.php"; 10 | wchar_t *httpsurl = L"https://www.google.com/"; 11 | 12 | char recv[10240] = {0}; 13 | char *pszPostData = "teststr=Hello+world&testval=42"; 14 | int recvlen = 0; 15 | wchar_t size[50] = L""; 16 | 17 | WinHttpInit(); 18 | 19 | recvlen = SendHttpRequest(L"POST",pszServer,(UCHAR*)pszPostData,strlen(pszPostData)+1,recv,FALSE); 20 | 21 | printf("%s\n",recv); 22 | 23 | recvlen = SendHttpRequest(L"POST",server2,(UCHAR*)pszPostData,strlen(server2)+1,recv,FALSE); 24 | 25 | printf("%s\n",recv); 26 | //proxy test 27 | SetProxy(L"192.168.1.1:3128",L"",L""); 28 | 29 | recvlen = SendHttpRequest(L"POST",server2,(UCHAR*)pszPostData,strlen(server2)+1,recv,TRUE); 30 | 31 | printf("%s\n",recv); 32 | 33 | recvlen = SendHttpRequest(L"POST",httpsurl,(UCHAR*)pszPostData,strlen(httpsurl)+1,recv,FALSE); 34 | printf("%s\n",recv); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /WinHttpClient/winhttpclient.h: -------------------------------------------------------------------------------- 1 | #ifndef WIN_HTTP_H 2 | #define WIN_HTTP_H 3 | 4 | #include 5 | #include 6 | 7 | #pragma comment(lib, "Winhttp.lib") 8 | 9 | static const unsigned int INT_RETRYTIMES = 3; 10 | static wchar_t *SZ_AGENT = L"WinHttpClient"; 11 | static const int INT_BUFFERSIZE = 10240; // Initial 10 KB temporary buffer, double if it is not enough. 12 | 13 | typedef struct WIN_HTTP_CLIENT 14 | { 15 | wchar_t m_proxy[MAX_PATH]; 16 | wchar_t m_proxyUsername[50]; 17 | wchar_t m_proxyPassword[50]; 18 | 19 | wchar_t m_userAgent[50]; 20 | DWORD m_dwLastError; 21 | BOOL m_requireValidSsl; 22 | 23 | unsigned int m_resolveTimeout; 24 | unsigned int m_connectTimeout; 25 | unsigned int m_sendTimeout; 26 | unsigned int m_receiveTimeout; 27 | 28 | }WinHttp,*LPWinHttp; 29 | 30 | WinHttp whpdata; 31 | 32 | void WinHttpInit(); 33 | void SetProxy(const wchar_t *proxyhost,const wchar_t *user, const wchar_t *passwd); 34 | void SetUserAgent(const wchar_t *useragent); 35 | 36 | int getLastError(); 37 | int SendHttpRequest(const wchar_t *verb, wchar_t *url, unsigned char *sendbuf,int sendbuflen, char *output,BOOL proxyFlah); 38 | 39 | #endif -------------------------------------------------------------------------------- /WinHttpClient/WinHttpClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 头文件 28 | 29 | 30 | -------------------------------------------------------------------------------- /WinHttpClient/WinHttpClient.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {C7A72068-3338-43D2-A6D0-C24FAFE843B0} 15 | WinHttpClient 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Level3 43 | Disabled 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | Level3 52 | MaxSpeed 53 | true 54 | true 55 | 56 | 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /WinHttpClient/winhttpclient.c: -------------------------------------------------------------------------------- 1 | #include "winhttpclient.h" 2 | #include 3 | 4 | void WinHttpInit() 5 | { 6 | memset(whpdata.m_proxy,'\0',sizeof(whpdata.m_proxy)); 7 | wcscpy(whpdata.m_userAgent,L"WinHTTP Client/1.0"); 8 | wcscpy(whpdata.m_proxyUsername,L""); 9 | wcscpy(whpdata.m_proxyPassword,L""); 10 | 11 | whpdata.m_requireValidSsl = FALSE; // In https, Accept any certificate while performing HTTPS request. 12 | whpdata.m_dwLastError = 0; 13 | whpdata.m_resolveTimeout = 0; 14 | whpdata.m_connectTimeout = 60000; 15 | whpdata.m_sendTimeout = 30000; 16 | whpdata.m_receiveTimeout = 30000; 17 | 18 | } 19 | 20 | /* 21 | * @Description: 设置http请求的代理服务器 22 | * 例如:“192.168.1.1:1080” 23 | */ 24 | void SetProxy(const wchar_t *proxyhost,const wchar_t *user, const wchar_t *passwd) 25 | { 26 | wcscpy(whpdata.m_proxy,proxyhost); 27 | if(wcslen(user) == 0) 28 | wcscpy(whpdata.m_proxyUsername,L""); 29 | else 30 | wcscpy(whpdata.m_proxyUsername,user); 31 | 32 | if(wcslen(passwd) == 0) 33 | wcscpy(whpdata.m_proxyPassword,L""); 34 | else 35 | wcscpy(whpdata.m_proxyPassword,passwd); 36 | } 37 | 38 | /* 39 | * @Description: 返回最后一次错误的错误代码 40 | * 41 | */ 42 | int getLastError() 43 | { 44 | return whpdata.m_dwLastError; 45 | } 46 | /* 47 | * @Description:发送和接收消息接口 48 | * verb:http请求形式,POST和GET 49 | * url:请求路径 50 | * sendbuf:要发送的数据 51 | * output:接收到的回复数据 52 | * poxyFlag:是否使用代理,1-使用,0-不使用 53 | */ 54 | int SendHttpRequest(const wchar_t *httpVerb, wchar_t *url, unsigned char *sendbuf,int sendbuflen, char *output,BOOL proxyFlah) 55 | { 56 | wchar_t verb[10]; 57 | BOOL bRetVal = TRUE; 58 | DWORD recvLen = 0; 59 | DWORD dwOpenRequestFlag; 60 | DWORD options; 61 | 62 | HINTERNET m_sessionHandle = NULL; 63 | HINTERNET hConnect = NULL; 64 | HINTERNET hRequest = NULL; 65 | 66 | wchar_t szHostName[MAX_PATH] = L""; 67 | wchar_t szURLPath[MAX_PATH * 4] = L""; 68 | URL_COMPONENTS urlComp; 69 | 70 | BOOL bGetReponseSucceed = FALSE; 71 | unsigned int iRetryTimes = 0; 72 | 73 | wchar_t hdsize[50] = L""; 74 | wchar_t m_additionalRequestHeaders[MAX_PATH*5] = L"Content-Length: "; 75 | WINHTTP_PROXY_INFO proxyInfo; 76 | wchar_t szProxy[MAX_PATH] = L""; 77 | 78 | BOOL bSendRequestSucceed = FALSE; 79 | WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig; 80 | WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions; 81 | 82 | DWORD dwWritten = 0; 83 | DWORD dwSize = 0; 84 | BOOL bResult = FALSE; 85 | DWORD dwcode = 0; 86 | unsigned int iMaxBufferSize = INT_BUFFERSIZE; 87 | unsigned int iCurrentBufferSize = 0; 88 | BYTE *pResponse; 89 | wchar_t *szStatusCode; 90 | DWORD dwRead; 91 | 92 | //url检查 93 | if(wcslen(url) <= 0) 94 | { 95 | whpdata.m_dwLastError = ERROR_PATH_NOT_FOUND; 96 | return -1; 97 | } 98 | wcscpy(verb,httpVerb); 99 | if (_wcsicmp(verb, L"GET") == 0) 100 | { 101 | wcscpy(verb, L"GET"); 102 | } 103 | else if (_wcsicmp(verb, L"POST") == 0) 104 | { 105 | wcscpy(verb, L"POST"); 106 | } 107 | else 108 | { 109 | whpdata.m_dwLastError = ERROR_INVALID_PARAMETER; 110 | return -1; 111 | } 112 | 113 | m_sessionHandle = WinHttpOpen(whpdata.m_userAgent, 114 | WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 115 | WINHTTP_NO_PROXY_NAME, 116 | WINHTTP_NO_PROXY_BYPASS, 117 | 0); 118 | if (m_sessionHandle == NULL) 119 | { 120 | whpdata.m_dwLastError = GetLastError(); 121 | 122 | return -1; 123 | } 124 | 125 | WinHttpSetTimeouts(m_sessionHandle,whpdata.m_resolveTimeout,whpdata.m_connectTimeout,whpdata.m_sendTimeout,whpdata.m_receiveTimeout); 126 | 127 | memset(&urlComp, 0, sizeof(urlComp)); 128 | urlComp.dwStructSize = sizeof(urlComp); 129 | urlComp.lpszHostName = szHostName; 130 | urlComp.dwHostNameLength = MAX_PATH; 131 | urlComp.lpszUrlPath = szURLPath; 132 | urlComp.dwUrlPathLength = MAX_PATH * 5; 133 | urlComp.dwSchemeLength = 1; // None zero 134 | 135 | if (WinHttpCrackUrl(url,wcslen(url), 0, &urlComp)) 136 | { 137 | hConnect = WinHttpConnect(m_sessionHandle, szHostName, urlComp.nPort, 0); 138 | if(hConnect != NULL) 139 | { 140 | dwOpenRequestFlag = (urlComp.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0; 141 | hRequest = WinHttpOpenRequest(hConnect, 142 | verb, 143 | urlComp.lpszUrlPath, 144 | NULL, 145 | WINHTTP_NO_REFERER, 146 | WINHTTP_DEFAULT_ACCEPT_TYPES, 147 | dwOpenRequestFlag); 148 | 149 | if(hRequest != NULL) 150 | { 151 | // If HTTPS, then client is very susceptable to invalid certificates 152 | // Easiest to accept anything for now 153 | if (!whpdata.m_requireValidSsl && urlComp.nScheme == INTERNET_SCHEME_HTTPS) 154 | { 155 | options = SECURITY_FLAG_IGNORE_CERT_CN_INVALID| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID| SECURITY_FLAG_IGNORE_UNKNOWN_CA; 156 | 157 | WinHttpSetOption(hRequest, 158 | WINHTTP_OPTION_SECURITY_FLAGS, 159 | (LPVOID)&options, 160 | sizeof(DWORD)); 161 | } 162 | 163 | //发送请求失败时,多尝试几次 164 | while (!bGetReponseSucceed && iRetryTimes++ < INT_RETRYTIMES) 165 | { 166 | // memcpy(hdsize,&sendbuflen,sizeof(int)); 167 | swprintf(hdsize,50,L"%d",sendbuflen); 168 | 169 | wcscat(m_additionalRequestHeaders,hdsize); 170 | wcscat(m_additionalRequestHeaders,L"\r\nContent-Type: application/x-www-form-urlencoded\r\n"); 171 | 172 | if (!WinHttpAddRequestHeaders(hRequest, m_additionalRequestHeaders, wcslen(m_additionalRequestHeaders), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) 173 | { 174 | whpdata.m_dwLastError = GetLastError(); 175 | } 176 | 177 | if(proxyFlah) 178 | { 179 | memset(&proxyInfo, 0, sizeof(proxyInfo)); 180 | proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 181 | wcscpy_s(szProxy, MAX_PATH, whpdata.m_proxy); 182 | proxyInfo.lpszProxy = szProxy; 183 | if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo))) 184 | { 185 | whpdata.m_dwLastError = GetLastError(); 186 | } 187 | if(wcslen(whpdata.m_proxyUsername) > 0) 188 | { 189 | if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, (LPVOID)whpdata.m_proxyUsername, wcslen(whpdata.m_proxyUsername) * sizeof(wchar_t))) 190 | { 191 | whpdata.m_dwLastError = GetLastError(); 192 | } 193 | if (wcslen(whpdata.m_proxyPassword) > 0) 194 | { 195 | if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (LPVOID)whpdata.m_proxyPassword, wcslen(whpdata.m_proxyUsername) * sizeof(wchar_t))) 196 | { 197 | whpdata.m_dwLastError = GetLastError(); 198 | } 199 | } 200 | } 201 | 202 | } 203 | 204 | if (WinHttpSendRequest(hRequest, 205 | WINHTTP_NO_ADDITIONAL_HEADERS, 206 | 0, 207 | WINHTTP_NO_REQUEST_DATA, 208 | 0, 209 | 0, 210 | NULL)) 211 | { 212 | bSendRequestSucceed = TRUE; 213 | } 214 | else 215 | { 216 | // Query the proxy information from IE setting and set the proxy if any. 217 | memset(&proxyConfig, 0, sizeof(proxyConfig)); 218 | if (WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig)) 219 | { 220 | if (proxyConfig.lpszAutoConfigUrl != NULL) 221 | { 222 | memset(&autoProxyOptions, 0, sizeof(autoProxyOptions)); 223 | autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL; 224 | autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP; 225 | autoProxyOptions.lpszAutoConfigUrl = proxyConfig.lpszAutoConfigUrl; 226 | autoProxyOptions.fAutoLogonIfChallenged = TRUE; 227 | autoProxyOptions.dwReserved = 0; 228 | autoProxyOptions.lpvReserved = NULL; 229 | 230 | memset(&proxyInfo, 0, sizeof(proxyInfo)); 231 | 232 | if (WinHttpGetProxyForUrl(m_sessionHandle,url, &autoProxyOptions, &proxyInfo)) 233 | { 234 | if (WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo))) 235 | { 236 | if (WinHttpSendRequest(hRequest, 237 | WINHTTP_NO_ADDITIONAL_HEADERS, 238 | 0, 239 | WINHTTP_NO_REQUEST_DATA, 240 | 0, 241 | 0, 242 | NULL)) 243 | { 244 | bSendRequestSucceed = TRUE; 245 | } 246 | } 247 | if (proxyInfo.lpszProxy != NULL) 248 | { 249 | GlobalFree(proxyInfo.lpszProxy); 250 | } 251 | if (proxyInfo.lpszProxyBypass != NULL) 252 | { 253 | GlobalFree(proxyInfo.lpszProxyBypass); 254 | } 255 | } 256 | else 257 | { 258 | whpdata.m_dwLastError = GetLastError(); 259 | } 260 | } 261 | else if(proxyConfig.lpszProxy != NULL) 262 | { 263 | memset(&proxyInfo, 0, sizeof(proxyInfo)); 264 | proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 265 | memset(szProxy,0,sizeof(szProxy)); 266 | wcscpy_s(szProxy, MAX_PATH, proxyConfig.lpszProxy); 267 | proxyInfo.lpszProxy = szProxy; 268 | 269 | if (proxyConfig.lpszProxyBypass != NULL) 270 | { 271 | wchar_t szProxyBypass[MAX_PATH] = L""; 272 | wcscpy_s(szProxyBypass, MAX_PATH, proxyConfig.lpszProxyBypass); 273 | proxyInfo.lpszProxyBypass = szProxyBypass; 274 | } 275 | 276 | if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo))) 277 | { 278 | whpdata.m_dwLastError = GetLastError(); 279 | } 280 | } 281 | if (proxyConfig.lpszAutoConfigUrl != NULL) 282 | { 283 | GlobalFree(proxyConfig.lpszAutoConfigUrl); 284 | } 285 | if (proxyConfig.lpszProxy != NULL) 286 | { 287 | GlobalFree(proxyConfig.lpszProxy); 288 | } 289 | if (proxyConfig.lpszProxyBypass != NULL) 290 | { 291 | GlobalFree(proxyConfig.lpszProxyBypass); 292 | } 293 | } 294 | else 295 | { 296 | whpdata.m_dwLastError = GetLastError(); 297 | } 298 | } 299 | if (bSendRequestSucceed) 300 | { 301 | if (sendbuflen > 0) 302 | { 303 | if (!WinHttpWriteData(hRequest, 304 | sendbuf, 305 | sendbuflen, 306 | &dwWritten)) 307 | { 308 | whpdata.m_dwLastError = GetLastError(); 309 | } 310 | } 311 | if (WinHttpReceiveResponse(hRequest, NULL)) 312 | { 313 | dwSize = 0; 314 | bResult = WinHttpQueryHeaders(hRequest, 315 | WINHTTP_QUERY_STATUS_CODE, 316 | WINHTTP_HEADER_NAME_BY_INDEX, 317 | NULL, 318 | &dwSize, 319 | WINHTTP_NO_HEADER_INDEX); 320 | 321 | if (bResult || (!bResult && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))) 322 | { 323 | szStatusCode =(wchar_t*)malloc(sizeof(wchar_t)*dwSize); 324 | memset(szStatusCode,0,sizeof(wchar_t)*dwSize); 325 | 326 | memset(szStatusCode, 0, dwSize* sizeof(wchar_t)); 327 | 328 | WinHttpQueryHeaders(hRequest, 329 | WINHTTP_QUERY_STATUS_CODE, 330 | WINHTTP_HEADER_NAME_BY_INDEX, 331 | szStatusCode, 332 | &dwSize, 333 | WINHTTP_NO_HEADER_INDEX); 334 | 335 | 336 | } 337 | 338 | do 339 | { 340 | dwSize = 0; 341 | if (WinHttpQueryDataAvailable(hRequest, &dwSize)) 342 | { 343 | pResponse = (BYTE *)malloc(sizeof(BYTE)*(dwSize+1)); 344 | memset(pResponse,0,sizeof(BYTE)*(dwSize+1)); 345 | dwRead = 0; 346 | 347 | if (WinHttpReadData(hRequest, 348 | pResponse, 349 | dwSize, 350 | &dwRead)) 351 | { 352 | memcpy(output + iCurrentBufferSize, pResponse, dwRead); 353 | iCurrentBufferSize += dwRead; 354 | } 355 | free(pResponse); 356 | } 357 | } while (dwSize > 0); 358 | 359 | bGetReponseSucceed = TRUE; 360 | 361 | free(szStatusCode); 362 | } 363 | 364 | } 365 | 366 | } 367 | 368 | WinHttpCloseHandle(hRequest); 369 | } 370 | WinHttpCloseHandle(hConnect); 371 | } 372 | } 373 | WinHttpCloseHandle(m_sessionHandle); 374 | 375 | return iCurrentBufferSize; 376 | } 377 | --------------------------------------------------------------------------------