I’m new at pogramming and I have a problem that I cant solve. I have create a program that share files, like dropbox. I have a server, that is working fine and a client.
The problem is, when I’m trying to download a file from the server, it seems that some bytes are missing from the stream.
clientSocket = new TcpClient(Program.host, Program.port);
NetworkStream networkStream = clientSocket.GetStream();
StreamWriter write = new StreamWriter(networkStream);
write.WriteLine(need);
write.Flush();
write.WriteLine(loca);
write.Flush();
StreamReader read = new StreamReader(networkStream);
Int64 size = Convert.ToInt64(read.ReadLine());
long blocks = size / 1024;
long blocksDown = 0;
try
{
string fileName = string.Empty;
int qtd = 0;
int blockSize = 1024;
double progress = 0;
Int64 qtdDown = 0;
Byte[] dataByte = new Byte[blockSize];
bool download = true;
lock (this)
{
networkStream.Read(dataByte, 0, dataByte.Length);
int fileNameLen = BitConverter.ToInt32(dataByte, 0);
fileName = Encoding.ASCII.GetString(dataByte, 4, fileNameLen);
if (File.Exists(Program.loc + fileName))
switch (MessageBox.Show("Ficheiro já existente!\r\nDeseja Substituir?", "Aviso", MessageBoxButtons.YesNo,
MessageBoxIcon.Warning))
{
case DialogResult.Yes:
File.Delete(Program.loc + fileName);
download = true;
break;
case DialogResult.No:
download = false;
break;
}
if (download)
{
Stream fileStream = File.OpenWrite(Program.loc + fileName);
fileStream.Write(dataByte, 4 + fileNameLen, (1024 - (4 + fileNameLen)));
bool progChanged = false;
backWork.WorkerReportsProgress = true;
double progAnt = 0;
while (true)
{
qtd = networkStream.Read(dataByte, 0, blockSize);
qtdDown += qtd;
progress = (double)qtdDown * (double)100 / (double)size;
if (Math.Round(progress) > Math.Round(progAnt))
{
progChanged = true;
progAnt = progress;
}
if (Math.Round(progress) > 0 && progChanged)
{
backWork.ReportProgress(((int)Math.Round(progress)));
progChanged = false;
}
fileStream.Write(dataByte, 0, qtd);
fileStream.Flush();
blocksDown++;
if (qtd == 0)
{
backWork.ReportProgress(100);
qtd = networkStream.Read(dataByte, 0, blockSize);
networkStream.Close();
fileStream.Close();
break;
}
}
MessageBox.Show("O ficheiro " + fileName + " foi guardado em " + Program.loc + ".", "Download",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
This is what I’m doing. I’m doing the download on a Background worker.
First I write on the stream what I’m doing then I open the stream of the file, and then start reading the stream and writing to the file.
@Ňuf I tried what you said and still doesnt work
The code looks like this, and the bytes from qtdDown and size are not equal. Sorry if if there are some parts in portuguese, my native langage is portuguese.
btnAct.Enabled = false;
btnBro.Enabled = false;
btnDown.Enabled = false;
btnSend.Enabled = false;
menuStrip1.Enabled = false;
pBar.Value = 0;
clientSocket = new TcpClient(Program.host, Program.port);
NetworkStream networkStream = clientSocket.GetStream();
StreamWriter write = new StreamWriter(networkStream);
write.WriteLine(need);
write.Flush();
write.WriteLine(loca);
write.Flush();
int blockSize = 1024;
byte[] fileSizeBytes = new byte[blockSize];
networkStream.Read(fileSizeBytes, 0, blockSize);
string fileSizeString = Encoding.ASCII.GetString(fileSizeBytes, 0, fileSizeBytes.Length);
fileSize = Convert.ToInt64(fileSizeString);
qtdDown = 0;
try
{
string fileName = string.Empty;
int qtd = 0;
double progress = 0;
Byte[] dataByte = new Byte[blockSize];
bool download = true;
lock (this)
{
networkStream.Read(dataByte, 0, dataByte.Length);
int fileNameLen = BitConverter.ToInt32(dataByte, 0);
fileName = Encoding.ASCII.GetString(dataByte, 4, fileNameLen);
if (File.Exists(Program.loc + fileName))
switch (MessageBox.Show("Ficheiro já existente!\r\nDeseja Substituir?", "Aviso", MessageBoxButtons.YesNo,
MessageBoxIcon.Warning))
{
case DialogResult.Yes:
File.Delete(Program.loc + fileName);
download = true;
break;
case DialogResult.No:
download = false;
break;
}
if (download)
{
Stream fileStream = File.OpenWrite(Program.loc + fileName);
fileStream.Write(dataByte, 4 + fileNameLen, (1024 - (4 + fileNameLen)));
networkStream.ReadTimeout = 60;
backWork.WorkerReportsProgress = true;
double progAnt = 0;
while (true)
{
qtd = networkStream.Read(dataByte, 0, blockSize);
qtdDown += qtd;
progress = (double)qtdDown * (double)100 / (double)fileSize;
if (Math.Round(progress) > Math.Round(progAnt))
{
progAnt = progress;
backWork.ReportProgress(((int)Math.Round(progress)));
}
fileStream.Write(dataByte, 0, qtd);
if (qtdDown == fileSize)
{
backWork.ReportProgress(100);
fileStream.Close();
networkStream.Close();
break;
}
}
MessageBox.Show("O ficheiro " + fileName + " foi guardado em " + Program.loc + ".", "Download",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception ex)
{
menuStrip1.Enabled = true;
btnAct.Enabled = true;
btnBro.Enabled = true;
btnDown.Enabled = true;
btnSend.Enabled = true;
MessageBox.Show("Ocorreu um erro!" + "\r\nBytes Downloaded: "
+ qtdDown.ToString() + "\\" + fileSize.ToString() + "\r\nDetalhes do Erro: " + ex.Message, "Download",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
menuStrip1.Enabled = true;
btnAct.Enabled = true;
btnBro.Enabled = true;
btnDown.Enabled = true;
btnSend.Enabled = true;
You are loosing bytes by calling read.ReadLine(). Although this function returns only data from one line, it internally reads more data from network stream to internal buffer and keeps remaining data for subsequent read.Read() calls, which never happens in your code.
Read data either using StreamReader or read them directly from NetworkStrem, but do not mix readings from both together.