2008-09-18 1090 views

Respuesta

16

En la capa de aplicación (utilizando una API de estilo de socket Berkeley) solo mira el reloj, y lee o escribe datos a la velocidad que desea limitar.

Si solo lee 10kbps en promedio, pero la fuente está enviando más que eso, eventualmente todos los búferes entre él y usted se llenarán. TCP/IP lo permite, y el protocolo hará que el emisor se desacelere (en la capa de aplicación, probablemente todo lo que necesita saber es que, en el otro extremo, bloqueará las llamadas de escritura, las que no sean de bloqueo fallarán y las asincrónicas las escrituras no se completarán, hasta que haya leído suficientes datos para permitirlo).

En la capa de aplicación, solo puede ser aproximado: no puede garantizar límites duros, como "no más de 10 kb pasará un punto determinado de la red en cualquier segundo". Pero si realiza un seguimiento de lo que ha recibido, puede obtener el promedio correcto a la larga.

4

Suponiendo un transporte de red, basado en TCP/IP, los paquetes se envían en respuesta a los paquetes ACK/NACK que van por el otro camino.

Al limitar la tasa de paquetes que acusan recibo de los paquetes entrantes, a su vez se reducirá la velocidad a la que se envían los paquetes nuevos.

Puede ser un poco impreciso, por lo que es posiblemente óptimo para controlar la tasa de flujo descendente y ajustar la tasa de respuesta de forma adaptativa hasta que se encuentre dentro de un umbral confortable. (Esto sucederá realmente rápido, sin embargo, envía dosens of acks por segundo)

+0

¿No es necesario ir a la pila de TCP/IP de bajo nivel y pasar por alto la capa de socket estándar? – Branan

1

Si está leyendo desde un socket, no tiene control sobre el ancho de banda utilizado; está leyendo el buffer del sistema operativo de ese socket, y nada de lo que diga hará que la persona que escribe en el zócalo escriba menos datos (a menos que, por supuesto, haya elaborado un protocolo para eso).

Lo único que haría lentamente con la lectura sería llenar el búfer y provocar un eventual bloqueo en el extremo de la red, pero no tiene control sobre cómo y cuándo sucede esto.

Si realmente desea leer solamente tantos datos a la vez, se puede hacer algo como esto:

ReadFixedRate() { 
    while(Data_Exists()) { 
    t = GetTime(); 
    ReadBlock(); 
    while(t + delay > GetTime()) { 
     Delay()' 
    } 
    } 
} 
+0

Los almacenamientos intermedios tienen valores máximos. ¿Cache? No hay memoria caché involucrada. –

+0

Usted tiene, por supuesto, toda la razón. Eliminé las cosas de la memoria caché y agregué un poco sobre las memorias intermedias. – Branan

0

wget parece manejarlo con la opción de tasa --limit. Aquí hay de la página man:

Tenga en cuenta que Wget implementa el limitando por dormir la cantidad apropiada de tiempo después de una lectura de la red que se llevó a menos tiempo que el especificado por el tipo de . Finalmente, esta estrategia ocasiona que la transferencia TCP disminuya a aproximadamente la velocidad especificada. Sin embargo, puede tomar algún tiempo para lograr este equilibrio, por lo que no se sorprenda si la limitación de la tasa no funciona bien con archivos muy pequeños .

0

Como han dicho otros, el núcleo del sistema operativo está administrando el tráfico y simplemente está leyendo una copia de los datos de la memoria del kernel.Para limitar aproximadamente la velocidad de una sola aplicación, necesitas retrasar tus lecturas de los datos y permitir que los paquetes entrantes se almacenen en el kernel, lo que eventualmente ralentizará el reconocimiento de los paquetes entrantes y reducirá la velocidad en ese socket.

Si desea ralentizar todo el tráfico hacia la máquina, debe ir y ajustar los tamaños de sus búferes TCP entrantes. En Linux, afectaría este cambio al alterar los valores en/proc/sys/net/ipv4/tcp_rmem (leer tamaños de búfer de memoria) y otros archivos tcp_ *.

1

Es como cuando se limita un juego a un cierto número de FPS.

extern int FPS; 
....  
timePerFrameinMS = 1000/FPS; 

while(1) { 
time = getMilliseconds(); 
DrawScene(); 
time = getMilliseconds()-time; 
if (time < timePerFrameinMS) { 
    sleep(timePerFrameinMS - time); 
} 
} 

De esta manera, asegúrese de que la frecuencia de actualización del juego sea como máximo FPS. De la misma manera DrawScene puede ser la función utilizada para bombear bytes en la secuencia de socket.

0

Para añadir a la respuesta de Branan:

Si limita voluntariamente la velocidad de lectura en el extremo receptor, con el tiempo las colas se llenan en ambos extremos. Luego, el remitente bloqueará en su llamada de envío() o regresará de la llamada de envío() con una longitud de envío inferior a la duración esperada transferida a la llamada de envío().

Si el remitente no está preparado para tratar este caso durmiendo e intentando reenviar lo que no cabe en los búfers del sistema operativo, terminará teniendo problemas de conexión (el remitente puede detectar esto como un error) o perderá datos (el remitente puede descartar datos sin saber que no encajaban en los búferes del sistema operativo).

0

Configure los búferes de envío y recepción de zócalo pequeño, digamos 1k o 2k, de modo que el ancho de banda * demore el producto = el tamaño del búfer. Es posible que no pueda obtenerlo lo suficientemente pequeño a través de enlaces rápidos.

Cuestiones relacionadas