PDA

View Full Version : bandwidth control


Syrinx
10-06-2004, 05:58 AM
Assume an httpd is coded in the easy model(multi-threaded and blocking socket,one client per thread model).

Assume the bandwidth control is 5000 KB(the total downloaded bytes per second must be no more than 5000 KB per second)

Assume there are 100 con-current clients downloading.

Method:
5000 KB / 100 clients = 50 KB / Client
so if the appliction controls every client's download speed no more than 50 KB per second,it will control the bandwidth.

Problem:
all the clients(100 clients) have different download speed.Assume only 50 of them can reach 50 KB per second(they can have higher download speed only because they all are limited by the 50 KB download speed),the half rest onl have 20 KB per second. If so,there bandwidth is 50 KB * 50 + 20 KB * 50 = 3500 KB,which is much less than 5000 KB.

Any good method?

Thx in advance

Regard

crakhed
10-06-2004, 09:15 AM
can't that be accomplished using global speed limits? if you set global to 5000 then it will be a free-for-all between the 100 clients.

Syrinx
10-06-2004, 10:35 PM
Originally posted by CRaKHeD
can't that be accomplished using global speed limits? if you set global to 5000 then it will be a free-for-all between the 100 clients.

If it's free for all 100 clients,then the application must check every second for the total send packages(downloaded bytes) and since it's blocking,probably more than 1 second is needed to send the entire buffer,then how to limit the bandwidth?

darkone
10-09-2004, 02:34 AM
I'm assuming that application is running in multiple threads, and in single process:


/* global variables */
LONG volatile lAvailableBandwidth = 0; /* -1000000 = INFINITE */
HANDLE hSemaphore;
LONG volatile lThreadWaitCount = 0;
CRITICAL_SECTION csBandwidth;


/* send */
BOOL SendData(Socket, PCHAR pBuffer, LONG lSize)
{
WSABUF Buffer;
DWORD dwBytes;
BOOL bLoop;

bLoop = TRUE;
Buffer.buffer = pBuffer;

do {
if (lAvailableBandwidth == -1000000 ||
InterlockedDecrement(&lAvailableBandwidth) >= 0) {
Buffer.len = min(1024, lSize);

if (WSASend(Socket, &Buffer, 1, &dwBytes, 0, 0, 0) == SOCKET_ERROR) {
return FALSE;
}
Buffer.buf = &Buf.buffer[dwBytes];
lSize -= dwBytes;

} else {
EnterCriticalSection(&csBandwidth);
if (lAvailableBandwidth <= 0) {
lThreadWaitCount++;
LeaveCriticalSection(&csBandwidth);
if (WaitForSingleObject(hSemaphore, 2000) == WAIT_OBJECT_0) {
/* ???? */
return FALSE;
}
} else {
LeaveCriticalSection(&csBandwidth);
}
}
} while (lSize != 0);

return TRUE;
}



/* thread that manages throttling */
UINT WINAPI ThrottleThread(LPVOID lpNull)
{
LONG lReleaseCount = 0;

for (;bRunning;) {
EnterCriticalSection(&csBandwidth);
InterlockedExchange(&lAvailableBandwidth, 5000);
lReleaseCount = lThreadWaitCount;
lThreadWaitCount = 0;
LeaveCriticalSection(&csBandwidth);

if (lReleaseCount > 0) {
ReleaseSemaphore(hSemaphore, lReleaseCount, 0);
}
/* this could use multimediatimer for higher accuracy */
Sleep(1000);
}
}

Syrinx
10-09-2004, 03:20 AM
Thanks for the code,but I got some questions about the code above.

1.what is the initial count and max count for CreateSemaphore()
2.Buffer.len = min(1024, lSize); is it too small to send 1K
data every time?
3.I don't quiet understand the code
if (WaitForSingleObject(hSemaphore, 2000) == WAIT_OBJECT_0) {
/* ???? */
return FALSE;

if doesn't get signal in 2 second,why don't keep it in the loop but return FALSE;

darkone
10-09-2004, 04:05 AM
1. Initial count is zero, max count is some very high number.
2. 1024 is fine when throttling. You might want to alter the code so, that it sends more than 1024bytes when not throttling.
3. Oops, it should be != WAIT_OBJECT_0 :)

Syrinx
10-10-2004, 01:42 AM
Thx for the code,it works on the test,but the code
"Buffer.buf = &Buf.buffer[dwBytes];"
must be changed before make the code work.