Pergunta

i have file transfer application [server- client] using tcp sockets.

when i send a single file, it success, but when i send a folder that contains many files, the received files got corrupted ,note that both of sent files from client and received files from the server have the same size(same count of bytes).

enter image description here

server:

private void ReceiveX(Socket client, string destPath, long size, int bufferSize)
    {
        using (Stream stream = File.Create(destPath))
        {
            byte[] buffer = new byte[bufferSize];
            long sum = 0;
            int count = 0;
            do
            {
                count = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                stream.Write(buffer, 0, count);
                sum += count;
            } while (sum < size);
        }
    }

client :

private void SendX(Socket socket, string filePath, long size, int bufferSize, DoWorkEventArgs e)
    {
        using (Stream stream = File.OpenRead(filePath))
        {
            byte[] buffer = new byte[bufferSize];
            long sum = 0;
            int count = 0;
            do
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                count = stream.Read(buffer, 0, buffer.Length);
                socket.Send(buffer, 0, count, SocketFlags.None);
                sum += count;
                worker.ReportProgress((int)((sum * 100) / size));
            } while (sum < size);
        }
    }

the bufferSize is [4 * 1024] for both client and server
Is there any wrong with the code above?

client : here i loop over the folder to send files:

private void SendDir(string path, int bufferSize, DoWorkEventArgs e)
    {
        using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
            listener.Bind(endpoint);
            listener.Listen(1);
            client.ReceiveFolder((IPEndPoint)listener.LocalEndPoint, fileList, Path.Combine(currAddress,Path.GetFileName(path)),bufferSize);
            Socket socket = listener.Accept();
            int count = 0;
    foreach (_File file in fileList)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                Console.WriteLine(++count);
                SendX(socket, file.Path, file.Size, bufferSize, e);
            }
            socket.Dispose();
    }

server ,loop over files in list<_File> which received from the server before, it contains the files info (name,path,size) that client is going to send :

 private void ReceiveFolderTh(IPEndPoint endpoint, List<_File> Files, string destDir, int bufferSize)
    {
        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Connect(IPAddress.Parse("127.0.0.1"), endpoint.Port);
        foreach (_File file in Files)
        {
            Directory.CreateDirectory(destDir  + Path.GetDirectoryName(file.Name));
            ReceiveX(client, destDir + file.Name, file.Size, bufferSize);
        }
        client.Dispose();
    }

so how can i fix that?

Foi útil?

Solução

Quite possibly the problem is that your client is receiving too much data on the first file because you have no clear separation between files. Your receive code is:

do
{
    count = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
    stream.Write(buffer, 0, count);
    sum += count;
} while (sum < size);

You always receive up to buffer.Length (which you say is 4,096) bytes. So if the first file is 100 bytes long and the next file is 5,000 bytes long, it's quite possible that the server is sending a packet of 4,096 bytes, which your code will dutifully receive and store in the first file.

You need to change the number of bytes to receive in your call to client.Receive. Something like:

int bytesToReceive = Math.Min(buffer.Length, size - sum);
count = client.Receive(buffer, 0, bytesToReceive, SocketFlags.None);

That will prevent you from reading beyond the end of one file and into the start of the next one.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top