0

tcpソケットを使用したファイル転送アプリケーション[サーバークライアント]があります。

単一のファイルを送信すると成功しますが、多くのファイルを含むフォルダーを送信すると、受信したファイルが破損します。クライアントから送信したファイルとサーバーから受信したファイルの両方が同じサイズ(同じバイト数)であることに注意してください。 )。

ここに画像の説明を入力してください

サーバ:

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

クライアント :

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

bufferSizeは、クライアントとサーバーの両方で[4 * 1024]
です。上記のコードに問題はありますか?

クライアント:ここで私はファイルを送信するためにフォルダーをループします:

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

list<_File>サーバー、以前にサーバーから受信したファイルをループします。これには、クライアントが送信するファイル情報(名前、パス、サイズ)が含まれます。

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

どうすればそれを修正できますか?

4

1 に答える 1

0

おそらく問題は、ファイル間の明確な分離がないために、クライアントが最初のファイルで受信するデータが多すぎることです。受信コードは次のとおりです。

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

あなたは常に最大buffer.Length(あなたが言うには4,096)バイトを受け取ります。したがって、最初のファイルの長さが100バイトで、次のファイルの長さが5,000バイトの場合、サーバーが4,096バイトのパケットを送信している可能性があります。このパケットは、コードが忠実に受信して最初のファイルに保存します。

への呼び出しで受信するバイト数を変更する必要がありますclient.Receive。何かのようなもの:

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

これにより、あるファイルの終わりを超えて次のファイルの先頭まで読み取ることができなくなります。

于 2012-04-24T04:42:35.803 に答える