내 파일 전송 서비스를 작업 중이므로 WCF 스트리밍으로 파일을 잘 전송할 수 있습니다. 나는 좋은 속도를 얻었고, 스트리밍하기 전에 작은 파일에 내 파일을 덩어리 때문에 좋은 이력서 지원을 할 수있게되었습니다.스트리밍 작업을 수행 할 때 어떻게 세분성을 향상시킬 수 있습니까?
그러나 메시지가 스트리밍 및 기록 될 때 상세한 전송 속도를 측정 할 때 서버 측 전송과 클라이언트 측 수신 모두에서 문제가 발생합니다.
다음은 파일이 청크 된 코드입니다.이 코드는 클라이언트가 다른 청크를 클라이언트에 보내야 할 때마다 서비스에서 호출합니다. 위에서
public byte[] NextChunk()
{
if (MoreChunks) // If there are more chunks, procede with the next chunking operation, otherwise throw an exception.
{
byte[] buffer;
using (BinaryReader reader = new BinaryReader(File.OpenRead(FilePath)))
{
reader.BaseStream.Position = currentPosition;
buffer = reader.ReadBytes((int)MaximumChunkSize);
}
currentPosition += buffer.LongLength; // Sets the stream position to be used for the next call.
return buffer;
}
else
throw new InvalidOperationException("The last chunk of the file has already been returned.");
, 나는 기본적으로 내가 사용하고 청크 크기에 따라 버퍼에 기록 (이 경우에는 내가 최고 전송 속도 크거나 작은 덩어리가 크기에 비해이 발견되는 2메가바이트이다). 그런 다음 약간의 작업을 수행하여 내가 중단 한 부분을 기억하고 버퍼를 반환합니다.
다음 코드는 서버 측 작업입니다. 은 WCF 호출의 클라이언트에 의해 호출되는이 방법에서
public FileMessage ReceiveFile()
{
if (!transferSpeedTimer.Enabled)
transferSpeedTimer.Start();
byte[] buffer = chunkedFile.NextChunk();
FileMessage message = new FileMessage();
message.FileMetaData = new FileMetaData(chunkedFile.MoreChunks, buffer.LongLength);
message.ChunkData = new MemoryStream(buffer);
if (!chunkedFile.MoreChunks)
{
OnTransferComplete(this, EventArgs.Empty);
Timer timer = new Timer(20000f);
timer.Elapsed += (sender, e) =>
{
StopSession();
timer.Stop();
};
timer.Start();
}
//This needs to be more granular. This method is called too infrequently for a fast and accurate enough progress of the file transfer to be determined.
TotalBytesTransferred += buffer.LongLength;
return message;
}
, 나는 다음 청크에 대한 정보를 얻을, 전송이 완료되면 내 세션을 중지하는 타이머와 조금을, 내 메시지를 작성하고 전송 속도를 업데이트하십시오. 내가 메시지를 반환하기 직전에, 내
TotalBytesTransferred
을 버퍼의 길이로 증가시켜 전송 속도를 계산하는 데 사용됩니다.
이 문제는 파일을 클라이언트로 스트리밍하는 데 시간이 걸리므로 속도가 틀립니다. 여기서 목표로 삼고 자하는 것은 TotalBytesTransferred
변수를 좀 더 세부적으로 수정 한 것이므로 주어진 시간에 얼마나 많은 데이터가 클라이언트에 전송되는지 더 잘 표현할 수 있습니다.
이제는 전송 속도를 완전히 다른 방식으로 계산하는 클라이언트 측 코드입니다. 여기
if (Role == FileTransferItem.FileTransferRole.Receiver)
{
hostChannel = channelFactory.CreateChannel();
((IContextChannel)hostChannel).OperationTimeout = new TimeSpan(3, 0, 0);
bool moreChunks = true;
long bytesPreviousPosition = 0;
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(fileWritePath)))
{
writer.BaseStream.SetLength(0);
transferSpeedTimer.Elapsed += ((sender, e) =>
{
transferSpeed = writer.BaseStream.Position - bytesPreviousPosition;
bytesPreviousPosition = writer.BaseStream.Position;
});
transferSpeedTimer.Start();
while (moreChunks)
{
FileMessage message = hostChannel.ReceiveFile();
moreChunks = message.FileMetaData.MoreChunks;
writer.BaseStream.Position = filePosition;
// This is golden, but I need to extrapolate it out and do the stream copy myself so I can do calculations on a per byte basis.
message.ChunkData.CopyTo(writer.BaseStream);
filePosition += message.FileMetaData.ChunkLength;
// TODO This needs to be more granular
TotalBytesTransferred += message.FileMetaData.ChunkLength;
}
OnTransferComplete(this, EventArgs.Empty);
}
}
else
{
transferSpeedTimer.Elapsed += ((sender, e) =>
{
totalElapsedSeconds += (int)transferSpeedTimer.Interval;
transferSpeed = TotalBytesTransferred/totalElapsedSeconds;
});
transferSpeedTimer.Start();
host.Open();
}
, 내
TotalBytesTransferred
또한 덩어리가 들어오는 길이를 기반으로합니다. 나는, 내가 스트림 자신을 쓰는 대신 스트림의
CopyTo
를 사용을 할 경우 내가 좀 더 세부적인 계산을 얻을 수 있습니다 알고 있지만 이 일에 최선을 다하는 방법을 정확히 모르겠다.
아무도 나를 도와 줄 수 있습니까? 이 클래스 밖에서 나는 내부적으로 업데이트 된 TransferSpeed
속성을 폴링하는 또 다른 클래스를 가지고 있습니다.
너무 많은 코드를 게시하면 사과하지만 게시 할 내용과 그렇지 않은 내용을 잘 모릅니다.
편집 : 나는 적어도 서버 측 구현, 내가 전송 된 바이트 수에 대한 더 세부적인 독서를 얻을 수있는 방법은, 스트림의 반환 메시지 값의 위치를 읽는 것입니다 알고 있습니다. 그러나, 나는 나의 카운트에서 절대적인 무결성을 보장하기 위해 이것을하는 방법을 모른다. 스트림을 전송할 때 타이머를 사용하고 위치를 폴링하는 방법에 대해 생각했지만 다음 호출이 이루어질 수 있으며 신속하게 동기화되지 않게됩니다.
반환되는 스트림에서 데이터를 폴링하고 스트림이 끝날 때 즉시 알 수 있으므로 스트림의 나머지 부분을 바이트 수에 빠르게 추가 할 수 있습니까?