Błażej
Błażej

Reputation: 3635

TcpClient VS Socket in large file transfer

I have to trnasfer large file, at this moment I use TcpClient and NetworkStream class to do that, but it isn't enought. When I use NetworkStream.Write and Read it lose bytes I don't know how can I ensure that TCP will stop reading when all bytes will be ok.

Then I found Socket Class, and now my question, "Socket will be perfectly sure about all bytes before it end read?"

How I recive file:

            byte[] VideoFrom = new byte[FizeSizeSendedBefore];
            byte[] PartData = new byte[clientSocket.ReceiveBufferSize];
            int PartNumbers = (VideoSize / clientSocket.ReceiveBufferSize) + 1;
            int lastPackageSize = VideoSize - ((PartNumbers - 1) * clientSocket.ReceiveBufferSize);

            int i;
            int bytesToRead = 0;
            int ActualSize = 0;
            for (i = 0; i < PartNumbers; i++)
            {
                if (i < PartNumbers - 1)
                {
                    bytesToRead = clientSocket.ReceiveBufferSize;
                }
                else
                {

                    bytesToRead = lastPackageSize;
                }
                ActualSize += bytesToRead;


                PartData = new byte[bytesToRead];

                System.Threading.Thread.Sleep(2);

                networkStream.Read(PartData, 0, bytesToRead);

                Buffer.BlockCopy(PartData, 0, VideoFrom, i * clientSocket.ReceiveBufferSize, bytesToRead);
            }



            if (!Directory.Exists("./temp/anwsers/" + AnwserXML.Attribute("number").Value)) { Directory.CreateDirectory("./temp/anwsers/" + AnwserXML.Attribute("number").Value); }
            File.WriteAllBytes("./temp/anwsers/" + AnwserXML.Attribute("number").Value + "/" + AnwserXML.Attribute("client").Value + ".mov", VideoFrom);


        }

How I send file

int PartNumber = (FizeSizeSendedBefore/ clientSocket.ReceiveBufferSize) + 1;
            int lastPackageSize = FileSize - ((PartNumber - 1) * clientSocket.ReceiveBufferSize);
            int i;
            for (i = 0; i < PartNumber; i++)
            {
                if (i < PartNumber - 1)
                {
                    while (!serverStream.CanRead) { }
                    serverStream.Write(outStream, i * clientSocket.ReceiveBufferSize, clientSocket.ReceiveBufferSize);
                }
                else
                {
                    while (!serverStream.CanRead) { }
                    serverStream.Write(outStream, i * clientSocket.ReceiveBufferSize, lastPackageSize);
                }

            }

Upvotes: 2

Views: 4521

Answers (3)

Aleksej Vasinov
Aleksej Vasinov

Reputation: 2797

How large is your file? Maybe it will be enough WebClient.DownloadDataAsync(...)?

UPDATED If file is about 100Mb use simple WebClient :)

        WebClient wc = new WebClient();
        wc.DownloadDataCompleted += new DownloadDataCompletedEventHandler(OnDownloadDataCompleted);
        wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
        wc.DownloadDataAsync(new Uri("http://www.xxxx.com/t.tar.gz"));

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500385

This is the problem:

networkStream.Read(PartData, 0, bytesToRead);

Never ignore the return value of Read. Never assume that a single call to read will read all of the data. You need to loop round, reading until it's all "in". The number of calls to Read which are required to read all data is pretty much unrelated to the number of calls to Write. TCP is a stream protocol - treat it that way.

It's not clear whether you know exactly how much data you're expecting to read - do you? Will the server close the connection at the end? If so, and if you're using .NET 4, then you can get rid of a huge amount of this code:

using (Stream output = File.Create(filename))
{
    networkStream.CopyTo(output);
}

Upvotes: 6

Wolf5370
Wolf5370

Reputation: 1374

TCP will receive a chunk of data at a time - it will not lose data, but if you do not cater for the fact that data will be spilt into packets and will arrive one after the other and (often) not as one big "file", then you may not be listening for the rest of the data - this will seem like it is missing data, but really it is the code ignoring the rest after the first packet is received. Just because you sedn it in one lumnp, this does not mean it will arrive in one lump.

There are many examples of TCP server/client apps (and chat apps) out there in the wonderful world of google for you to compare notes on - alternatively post your code and we can then see where the error is.

Upvotes: 0

Related Questions