Search code examples
c#file-transfercorrupt

Sent file has some corrupted data TCP sockets .. how to fix it?


I have problem with my transfer files application .. everything looks great and works the way it should be .. but then I discovered that some pieces of the sent file is corrupted.
Like when I send a video file (.MP4) it sent successfully but when I play it some frames of it got corrupted like in the snapshot picture .. I played the source Mp4 file and the picture was so perfect and never looked like in that snapshot picture.
So here's my code .. I'm confused now about using fs.Seek .. someone told me it doesn't make the new file the same as the source file.

I'm using SOCKETS TCP .. (.Net 4.0)

enter image description here

Send method (CLIENT):

FileStream fs;
long sum;
long fileSize;
byte[] data = null;
NetworkStream network; 
const int packetSize = 1024*8;

private void SendFile(string srcPath, string destPath)
    {
        string dest = Path.Combine(destPath, Path.GetFileName(srcPath));
        using (fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read))
        {
            try
            {
                sum = 0;
                int count = 0;
                data = new byte[packetSize];
                //send the destination path and the file size to SERVER.
                SendCommand("receive<" + dest + "<" + fs.Length.ToString());
                while (sum < fileSize)
                {
                    if (fileSize - sum < packetSize)
                    {
                        count = fs.Read(data, 0, Convert.ToInt32(fileSize - sum));
                        network.Write(data, 0, Convert.ToInt32(fileSize - sum));
                    }
                    else
                    {
                        count = fs.Read(data, 0, data.Length);
                        network.Write(data, 0, data.Length);
                    }
                    fs.Seek(sum, SeekOrigin.Begin);
                    sum += count;
                    backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
                }
                network.Flush();
            }
            finally
            {
                fs.Dispose();
                data = null;
            }
        }
    }

Receive method (SERVER):

FileStream fs;
long sum;
long fileSize;
byte[] data = null;
NetworkStream network; 
const int packetSize = 1024*8;

public void Receive(string destPath, long fileSize)
    {
        using (fs = new FileStream(destPath, FileMode.Create, FileAccess.Write))
        {
            try
            {
                int count = 0;
                long sum = 0;
                data = new byte[packetSize];
                while (sum < fileSize)
                {
                    if (fileSize - sum < packetSize)
                    {
                        count = network.Read(data, 0, Convert.ToInt32(fileSize - sum));
                        fs.Write(data, 0, Convert.ToInt32(fileSize - sum));
                    }
                    else
                    {
                        count = network.Read(data, 0, data.Length);
                        fs.Write(data, 0, data.Length);
                    }
                    fs.Seek(sum, SeekOrigin.Begin);
                    sum += count;
                }
            }
            finally
            {
                fs.Dispose();
                data = null;
            }
        }
    }

Solution

  • In case you didn't solve it by now, I propose this code. Put it inside while (sum < fileSize).

    Send:

        count = fs.Read(data, 0, packetSize);
        network.Write(data, 0, count);
        sum += count;
        backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
    

    and Receive:

        count = network.Read(data, 0, packetSize);
        fs.Write(data, 0, count);
        sum += count;
    

    This will ensure that you transfer just the data you have read. Notice that you do not need if part because Read will return number of bytes read, so it doesn't matter if you are at beginning or at end of the file, Read will read all it can up to limit you provided as parameter.