Web Debug

Fix broken web applications, from servers to clients.

WinInet connection limit

WinInet limits connections per server

WinInet limits connections to a single HTTP 1.0 server to four simultaneous connections. Connections to a single HTTP 1.1 server are limited to two simultaneous connections. The HTTP 1.1 specification (RFC2616) mandates the two-connection limit. The four-connection limit for HTTP 1.0 is a self-imposed restriction that coincides with the standard that is used by a number of popular Web browsers.

The only evidence of this limitation to your application is that calls such as HttpSendRequest and InternetOpenURL appear to take longer to complete because they wait for previous connections to be freed up before their requests are sent.

You can configure WinInet to exceed this limit by creating and setting the following registry entries:

Note By changing these settings, you cause WinInet to go against the HTTP protocol specification recommendation. You should only do this if absolutely necessary and then you should avoid doing standard Web browsing while these settings are in effect:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
MaxConnectionsPerServer REG_DWORD
(Default 2)
Sets the number of simultaneous requests to a single HTTP 1.1 Server, this value can be set from 2 to 128.

MaxConnectionsPer1_0Server REG_DWORD
(Default 4)
Sets the number of simultaneous requests to a single HTTP 1.0 Server

These settings are made for a particular user and will have no affect on other users who log on to the computer.

Below is a sample code to simulate the scenario, open up 10 connections using wininet.

[cpp]
#include
#include
#include #include

const int kBufferLength = 2048;
const int kThreadNumber = 10;
const int kSleepInterval = 10;

#pragma comment(lib, "wininet.lib")

unsigned __stdcall ThreadFunc( void* pArguments ){
TCHAR response_buffer[kBufferLength];
HINTERNET session, connection, file;
SYSTEMTIME local_time;
DWORD thread_id = GetCurrentThreadId();

/*GetLocalTime(&local_time);
printf("%02d:%02d.%03d\tThread %d opening connection...\n",
local_time.wMinute,
local_time.wSecond,
local_time.wMilliseconds,
thread_id);*/

session = InternetOpen(TEXT("WinInet demo"), 0, NULL, NULL, 0);
connection = InternetConnect(
session, TEXT("msdn.microsoft.com"),
INTERNET_DEFAULT_HTTP_PORT, NULL,
NULL, INTERNET_SERVICE_HTTP,
0, 0);
file = HttpOpenRequest(
connection, NULL,
TEXT("/en-us/library/aa384247(v=vs.85).aspx"), NULL,
NULL, NULL,
0, 0);

GetLocalTime(&local_time);
printf("%02d:%02d.%03d\tThread %d starting request...\n",
local_time.wMinute,
local_time.wSecond,
local_time.wMilliseconds,
thread_id);

DWORD num_bytes;
//memset(response_buffer, '\0', sizeof(response_buffer));
if(HttpSendRequest(file, NULL, 0, NULL, 0)){
while(InternetReadFile(
file, &response_buffer,_countof(response_buffer), &num_bytes)){
if(num_bytes == 0)
break;
//printf("%s",response_buffer);
//memset(response_buffer, '\0', sizeof(response_buffer));
}
}
GetLocalTime(&local_time);
printf("%02d:%02d.%03d\tThread %d ending request...\n",
local_time.wMinute,
local_time.wSecond,
local_time.wMilliseconds,
thread_id);

InternetCloseHandle(file);
InternetCloseHandle(connection);
InternetCloseHandle(session);
return 0;
}

int main(){
HANDLE threads[kThreadNumber];
unsigned thread_id;

printf( "Creating threads...\n" );
for(int i = 0; i < kThreadNumber; i++){
threads[i] = (HANDLE)_beginthreadex(
NULL, 0, &ThreadFunc, NULL, 0, &thread_id );
//printf("Thread %d is created...\n",thread_id);
Sleep(kSleepInterval);
}

WaitForMultipleObjects(kThreadNumber, threads, true, INFINITE);
printf("Downloading finished...\n");

for(int i = 0; i< kThreadNumber; i++)
CloseHandle( threads[i] );
}

[/cpp]

If you want to set the connection by InternetSetOption API, it may not working for you on IE 8.

Bug in WinInet+IE8: ignores max connections setting

Fork me on GitHub