views:

58

answers:

2

I am having trouble transferring a file to a client from a server program. A few problems I would like to address. First is that I make the byte array 6000 bytes big and its always that size. Is there a way to maintain the correct file size? Also with the way the code is now, the program hangs. It works when I take it out of the while loop on the client side. Help!!

Client:

 private void button1_Click(object sender, EventArgs e)
    {   
        BinaryWriter binWriter; 
        int i = -1;
        Byte[] bytes = new Byte[6000];

        NetworkStream clientStream = connTemp.GetStream();
        byte[] outstream = Encoding.ASCII.GetBytes(txtMessage.Text);
        clientStream.Write(outstream, 0, outstream.Length);


        while (i != 0)
        {
            try
            {
                if (clientStream.CanRead)
                {
                    i = clientStream.Read(bytes, 0, bytes.Length);

                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                break;
            }
        }


        binWriter = new BinaryWriter(File.Open("C:\\SeanLaunch\\log.rxlog",FileMode.Create));
        binWriter.Write(bytes);
        binWriter.Close();

    }

}

Server:

  Byte[] fileToSendAsByteArray = new Byte[6000];
  fileToSendAsByteArray = File.ReadAllBytes("C:\\Launch\\Test.rxlog");
  stream.Write(fileToSendAsByteArray, 0, fileToSendAsByteArray.Length);

EDIT!!!: I fixed the looping issue.

+1  A: 

The program will loop forever if CanRead remains false while i is non-zero. Or, it may be blocked on the Read call.

Debug your receive side to find out what's going on. Is it really hung, or just looping?

Add code to dump the data sent and received on each end to see how far you read OK before the problems arise.

Steve Townsend
+1  A: 

One problem is that you are writing the entire 6000 bytes to the stream even if you only read one byte from the file.

Use a FileStream to access the file and copy the content to the NetworkStream. Framework 4.0 has a nice function for this

FileStream fs = new FileStream(...);
fs.CopyTo(stream);

You can take a similar approach for the client side, just in reverse, copy from the NetworkStream to the target Stream.

Prior to Framework 4.0 you can implement you own CopyTo function. Something like this

public static long CopyStream(Stream source, Stream target)
{
  const int bufSize = 0x1000;
  byte[] buf = new byte[bufSize];

  long totalBytes = 0;
  int bytesRead = 0;

  while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
  {
    target.Write(buf, 0, bytesRead);
    totalBytes += bytesRead;
  }
  return totalBytes;
}
Chris Taylor
I need this to stick to .Net 3.5
Sean P
@Sean P, I added a sample implementation for a 3.5 compatible CopyStream function. These can be found all over the Internet, they are a dime a dozen.
Chris Taylor
I think you may have mistaken my question. i have no problem getting the file across. My problem is that the file is always the of the byte[]. Is there a way to trim it down to the actual size? Im debating passing the file size first then initializing the byte[] to the correct size.
Sean P
@Sean P, I think understood that was the problem. That is why I say "One problem is that you are writing the entire 6000 bytes to the stream". I offer the CopyTo/CopyStream as a solution to this since it will send only the content of the stream, so when sending the file it will send only the bytes that are in the file. This way you have no need to send the file size along the wire.
Chris Taylor
What if i did this? byte[] fileToSendAsByteArray = new byte[File.ReadAllBytes("C:\\SeanLaunch\\Test.rxlog").Length];
Sean P
Nevermind, that doesnt get around the client side allocation.
Sean P