2012-04-23 1 views
0

У меня есть приложение для передачи файлов [server-client] с использованием сокетов tcp.Как исправить передачу файлов, полученные файлы повреждены?

Когда я отправляю один файл, это успех, но когда я отправляю папку, содержащую много файлов, полученные файлы повреждаются, обратите внимание, что оба отправляемых файла с клиента и полученные файлы с сервера имеют одинаковый размер (то же количество байтов).

enter image description here

сервер:

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

размер буфера составляет [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(); 
    } 

так как я могу это исправить?

ответ

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 байт, а следующий файл имеет длину 5000 байт, вполне возможно, что сервер отправляет пакет из 4096 байт, который ваш код будет покорно получать и хранить в первом файле.

Необходимо изменить количество байтов для приема в вашем вызове client.Receive. Что-то вроде:

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

Это не позволит вам читать за пределами одного файла и в начале следующего.

+0

Я уже решил это так, Клиент: 'try {SendFile} наконец {socket.Receive (новый байт [1], SocketFlags.None); } 'и Server:' try {ReceiveFile} наконец {client.Send (новый байт [1], SocketFlags.None); } ', поэтому клиент будет ждать, пока сервер отправит байт, но вы выглядите лучше! какой из них быстрее? –

+0

Мой подход должен быть немного быстрее. –