Sent file has some corrupted data TCP sockets .. h

2019-09-08 06:57发布

问题:

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)

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;
            }
        }
    }

回答1:

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.



回答2:

You never take into consideration how many bytes you read from file or network stream. See your count variables in your server & client codes.

You should write count bytes to other stream after reading from input stream.

EDIT

Here is a sample from your code in Receive

count = network.Read(data, 0, data.Length);
fs.Write(data, 0, data.Length);

How can you be sure that you have read data.Length bytes