개인용 연습으로 Java에서 (간단한) 다운로더 응용 프로그램을 구현할 것입니다. 실행 중에 동시에 여러 파일을 다운로드하는 방식으로 여러 스레드에서 여러 작업을 실행하려고합니다.Java에서 다운로드 속도가 어떻게 제한 될 수 있습니까?
모든 다운로드 작업간에 공유되는 다운로드 속도 제한을 정의 할 수 있기를 원하지만 단일 다운로드 작업으로도 수행하는 방법을 모르겠습니다. 어떻게해야합니까? 구현하려는 솔루션은 무엇입니까?
감사합니다.
개인용 연습으로 Java에서 (간단한) 다운로더 응용 프로그램을 구현할 것입니다. 실행 중에 동시에 여러 파일을 다운로드하는 방식으로 여러 스레드에서 여러 작업을 실행하려고합니다.Java에서 다운로드 속도가 어떻게 제한 될 수 있습니까?
모든 다운로드 작업간에 공유되는 다운로드 속도 제한을 정의 할 수 있기를 원하지만 단일 다운로드 작업으로도 수행하는 방법을 모르겠습니다. 어떻게해야합니까? 구현하려는 솔루션은 무엇입니까?
감사합니다.
모든 다운로드를 관리하는 DownloadManager로 시작할 것입니다.
interface DownloadManager
{
public InputStream registerDownload(InputStream stream);
}
관리 된 대역폭에 참여하려는 모든 코드는 다운로드 관리자가 스트림을 읽기 전에 등록합니다. registerDownload() 메서드에서 관리자는 주어진 입력 스트림을 ManagedBandwidthStream
에 래핑합니다.
public class ManagedBandwidthStream extends InputStream
{
private DownloadManagerImpl owner;
public ManagedBandwidthStream(
InputStream original,
DownloadManagerImpl owner
)
{
super(original);
this.owner = owner;
}
public int read(byte[] b, int offset, int length)
{
owner.read(this, b, offset, length);
}
// used by DownloadManager to actually read from the stream
int actuallyRead(byte[] b, int offset, int length)
{
super.read(b, offset, length);
}
// also override other read() methods to delegate to the read() above
}
스트림은 read()에 대한 모든 호출이 다운로드 관리자에게 전달되도록 보장합니다.
class DownloadManagerImpl implements DownloadManager
{
public InputStream registerDownload(InputStream in)
{
return new ManagedDownloadStream(in);
}
void read(ManagedDownloadStream source, byte[] b, int offset, int len)
{
// all your streams now call this method.
// You can decide how much data to actually read.
int allowed = getAllowedDataRead(source, len);
int read = source.actuallyRead(b, offset, len);
recordBytesRead(read); // update counters for number of bytes read
}
}
대역폭 할당 전략은 getAllowedDataRead()를 구현하는 방법에 관한 것입니다.
대역폭을 조절하는 간단한 방법은 은 주어진 기간 (예 : 1 초)에 몇 바이트를 더 읽을 수 있는지 카운터를 유지하는 것입니다. read를 호출 할 때마다 카운터를 검사하여이를 사용하여 읽은 실제 바이트 수를 제한합니다. 타이머를 사용하여 카운터를 재설정합니다.
실제로 여러 스트림 사이에서 대역폭 할당은 기아를 피하고 공정성을 높이기 위해 매우 복잡 할 수 있지만 이는 공정한 시작을 제공합니다.
위대한, 코드 주셔서 감사합니다,이 날 시작 충분해야합니다! – JohnWithoutArms
좋습니다. 더 이상 사용하지 않는'allowed' 변수가 대역폭 사용에 어떻게 영향을 줄 수 있습니까? 대역폭을 제어 할 수있는 것은 여기에 없습니다. 실제로 대답은 무엇입니까? – EJP
눈을 감춰두면 눈에 띄지 않게됩니다. 내가 응답에서 말했듯이, 나는 많은 스트림들 사이에서 대역폭을 관리하기위한 패턴을 보여주고 있습니다. 물론, 앞으로 가서 downvote, 완벽하게 유효한 이유는 단지 당신이 쓰여진 것을 읽는 것을 귀찮게 할 수 없기 때문입니다. – mdma
그게 기본적으로 대부분이 질문은 절대로 안돼요 높은 수준, 그래서 내가 당신을 희망
(단지 wget
같은) 작업 리미터 방법 낮은 수준의 대답을 기대하지 마십시오. 일반적으로 어떤 네트워크 유틸리티를 사용할지 정의/결정해야합니다. 예를 들어 표준 Java 소켓을 열려고합니까? 어떤 써드 파티 네트워크 라이브러리를 사용할 것입니까? 사용 가능한 옵션 중 하나라도 익혔습니까?
가장 일반적인 의미에서 결정한 네트워킹 라이브러리를 통해 대역폭을 제어 할 수 있습니다. 비교적 간단한 수식이어야합니다.
대역폭 제한을 설정하는 일종의 객체 (소켓이라고 함)가 있습니다. 소켓의 대역폭 제한 (일반적으로)을 전체 대역폭/활성 연결 수로 설정합니다. 일부 연결에서 전체 대역폭 할당을 사용하지 않는 경우이 번호를 지속적으로 최적화 할 수 있습니다. 해당 알고리즘에 대한 도움을 요청하십시오.
방정식의 두 번째 부분은 OS/네트워크 라이브러리가 이미 속도를 제공하여 대역폭을 제어 할 수 있습니까? 또는 읽기/쓰기 속도를 제한하여이 프로세스를 직접 제어해야합니까? 이것은 OS가 TCP 소켓 버퍼를 가질 수 있기 때문에 보이는 것처럼 간단하지 않습니다. TCP 소켓 버퍼는 데이터가 가득 찰 때까지 읽습니다. 인바운드 트래픽을위한 2MB 소켓 버퍼가 있다고 가정합니다. 원격 측에서 2Mb 버퍼가 꽉 찼을 때 데이터 전송을 멈추는 것에 의존한다면 대기열에서 제거하여 속도 제한을 적용하기 전에 2Mb의 데이터가 전송 될 때까지 기다려야합니다. 속도 제한 전에 모든 소켓에.
그 시점에서 TCP (또는 UDP)를 통해 실행되는 프로토콜 작성에 대해 이야기하기 시작합니다. 즉, 한 쪽에서 다른 쪽에서 "Ok send more data"또는 "wait, my bandwidth limit is temporary 히트". 간단히 말하자면 구현을 시작한 후에 질문을하십시오.
CPU 사용률, 네트워크 대역폭, 기타는 무엇입니까? –