Pergunta

Suponha que você tenha um programa que lê a partir de uma tomada. Como você mantém a taxa de download abaixo de um determinado dado limiar?

Foi útil?

Solução

Na camada de aplicação (usando um Berkeley API estilo socket) que você acabou de olhar para o relógio, e ler ou gravar dados a uma taxa que pretende limitar a.

Se você apenas lê 10Kbps, em média, mas a fonte está enviando mais do que isso, então, eventualmente, todos os buffers entre ele e você vai encher-se. TCP / IP permite isso, e o protocolo vai mandar para o remetente para abrandar (na camada de aplicação, provavelmente tudo que você precisa saber é que, no outro extremo, o bloqueio de chamadas de escrita irão bloquear, escreve nonblocking irá falhar, e assíncrona escreve não completa, até que você ler dados suficientes para permitir que ele).

Na camada de aplicação que só pode ser aproximada - você não pode garantir limites rígidos como "não mais do que 10 kb vai passar um determinado ponto da rede em qualquer um segundo". Mas se você acompanhar o que você recebeu, você pode obter o direito média no longo prazo.

Outras dicas

Assumindo um transporte de rede, um baseado em TCP / IP, os pacotes são enviados em resposta aos pacotes de ACK / NACK indo para o outro lado.

Ao limitar a taxa de pacotes confirmando o recebimento dos pacotes de entrada, você vai por sua vez, reduzir a taxa em que novos pacotes são enviados.

Pode ser um pouco imprecisa, pelo que a sua, possivelmente, ideal para monitorar a taxa de jusante e ajustar a taxa de resposta adaptativa até que ele cai dentro de um limite confortável. (Isso vai acontecer muito rápido no entanto, você envia dosens de acks um segundo)

É como quando limitar um jogo para um certo número de FPS.

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

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

Desta forma, você se certificar de que a taxa de atualização jogo será no máximo FPS. Do mesmo modo DrawScene pode ser a função utilizada para bombear bytes no fluxo de tomada.

Se você está lendo a partir de um soquete, você não tem nenhum controle sobre a largura de banda utilizada - você está lendo tampão desse soquete do sistema operacional, e nada que você diga vai fazer a pessoa escrito ao write tomada menos dados (a menos , é claro, que você trabalhou um protocolo para isso).

Tudo o que ler devagar gostaria de fazer é preencher o buffer, e causar uma eventual tenda na extremidade da rede -, mas você não tem controle de como ou quando isso acontece

.

Se você realmente quer ler somente tanto dados de cada vez, você pode fazer algo como isto:

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

wget parece controlá-lo com a opção de taxa --limit. Aqui está a partir da página man:

Note que implementos Wget a limitação por dormir a quantidade adequada de tempo após uma rede ler que levou menos tempo do que o especificado pelo taxa. Eventualmente, esta estratégia faz com que a transferência TCP para abrandar a aproximadamente a taxa especificada. No entanto, isso pode levar algum tempo para este equilíbrio a ser alcançado, por isso não ser surpreendido se limitando a taxa não funciona bem com muito pequena arquivos.

Como outros já disseram, o kernel do sistema operacional é a gestão do tráfego e você está simplesmente lendo um exemplar dos dados fora da memória do kernel. Para cerca de limitar a taxa de apenas uma aplicação, você precisa atrasar a sua lê os dados e permitir pacotes de entrada para o buffer-se no kernel, o que acabará por atrasar o reconhecimento de pacotes de entrada e reduzir a taxa em que um soquete.

Se você quiser retardar todo o tráfego para a máquina, você precisa ir e ajustar os tamanhos de seus buffers TCP de entrada. No Linux, você iria afetar essa mudança alterando os valores em / proc / sys / net / ipv4 / tcp_rmem (tamanhos de buffer de memória de leitura) e outros tcp_ * arquivos.

Para adicionar a resposta de Branan:

Se você limitar voluntariamente a velocidade de leitura no final receptor, eventualmente, filas vai encher-se em ambas as extremidades. Em seguida, o remetente quer bloquear no seu apelo send () ou de retorno da chamada send () com um sent_length menor que o comprimento esperado passado para o envio de chamadas ().

Se o remetente não está pronto para lidar com este caso por dormir e tentar reenviar o que não se encaixam em buffers do sistema operacional, você vai acabar têm problemas de conexão (o remetente pode detectar isso como um erro) ou perda de dados (o remetente pode dados sem saber descartar a não se encaixam em buffers oS).

Set pequena tomada enviar e receber buffers, digamos 1k ou 2k, de modo que a largura de banda * atraso produto = o tamanho do buffer. Você pode não ser capaz de obtê-lo pequeno o suficiente sobre ligações rápidas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top