2012-04-13 3 views
0

J'ai un problème de transfert de fichiers réseau. Le téléchargement TCP/UDP de socket est plus lent que la copie native de Windows lorsqu'il y a plus d'un client.Pourquoi le transfert de fichiers de socket est plus lent que la copie de Windows?

J'ai un PC avec un réseau 1Gbps.

Voici les cas de copie de Windows.

Une copie du client à partir du serveur, la vitesse de téléchargement maximale est d'environ 100mbps. Deux clients copient à partir du serveur, la vitesse de téléchargement maximale est d'environ 200mbps. Trois clients copient à partir du serveur, la vitesse de téléchargement maximale est d'environ 300mbps.

Voici les boîtiers Socket.

Téléchargement d'un client à partir du serveur, la vitesse de téléchargement maximale est d'environ 100mbps.

Deux clients téléchargent à partir du serveur, la vitesse de téléchargement maximale est d'environ 100mbps.

Trois clients téléchargent à partir du serveur, la vitesse de téléchargement maximale est d'environ 100mbps.

Comme vous le voyez, la vitesse de téléchargement du serveur de socket n'augmente pas lorsque le nombre de clients augmente.

Nous avons créé un programme simple pour tester ce problème. Il rencontre les mêmes problèmes. C'est très simple d'envoyer et d'appeler recv. Veuillez vérifier les codes.

class Program 
{ 
    static List<TcpClient> sessions = new List<TcpClient>(); 

    static void Main(string[] args) 
    { 
     bool isServer = false; 
     Console.WriteLine("Run as a server? (Y/N)"); 
     string answer = Console.ReadLine(); 
     if (answer.ToUpper().StartsWith("Y")) isServer = true; 

     if (isServer) 
     { 
     TcpListener listener = new TcpListener(IPAddress.Any, 13579); 
     Console.WriteLine("Listening at: " + ((IPEndPoint)listener.LocalEndpoint).ToString()); 
     listener.Start(); 
     Thread workerThread = new Thread(() => 
     { 
      while (true) 
      { 
       lock (sessions) 
       { 
       foreach (var client in sessions) 
       { 
        if (client.Available > 0) 
        { 
         byte[] buffer = new byte[client.Available]; 
         int length = client.Client.Receive(buffer); 
         string filePath = Encoding.UTF8.GetString(buffer, 0, length); 

         if (File.Exists(filePath)) 
         { 
         foreach (var receiver in sessions) 
          receiver.Client.SendFile(filePath, null, null, TransmitFileOptions.UseKernelApc | TransmitFileOptions.WriteBehind); 
         } 
        } 
       } 
       } 
       Thread.Sleep(200); 
      } 

     }); 

     workerThread.IsBackground = true; 
     workerThread.Start(); 

     while (true) 
     { 
      TcpClient client = listener.AcceptTcpClient(); 
      lock (sessions) 
      { 
       sessions.Add(client); 
      } 
     } 
     } 
     else 
     { 
     Console.WriteLine("Enter the server IP:"); 
     string ipAddress = Console.ReadLine(); 
     TcpClient client = new TcpClient(ipAddress, 13579); 
     Console.WriteLine("Enter the file path on remote server:"); 
     string remoteFilePath = Console.ReadLine(); 
     if(remoteFilePath != "") 
        client.Client.Send(Encoding.UTF8.GetBytes(remoteFilePath)); 
     byte[] recvBuffer = new byte[32768]; 
     while(true) 
     { 
      try 
      { 
        client.Client.Receive(recvBuffer, 32768, SocketFlags.None); 
      } 
      catch (SocketException e) 
      { 
        Console.WriteLine("Transfer interrupted: {0}", e.Message); 
        break; 
      } 
     } 
     } 
    } 
} 

Ceci nous bloque l'implémentation de l'outil Socket avec de meilleures performances. Espérons que les gars de stackoverflow pourraient nous aider. Merci avancé.

+1

dépend de votre implémentation client/serveur que nous ne savons rien de. D'où la question est impossible de répondre. – jgauffin

+0

merci pour la réponse rapide, les codes joints. – OliverWho

+0

Exécutez-vous le code sur les mêmes machines que dans le cas d'un test avec Windows Copy? – nos

Répondre

1

Bien sûr, c'est plus lent. vous utilisez le même thread pour interroger tous les clients.

Vous devriez passer aux méthodes asynchrones dans le serveur (BeginRead/EndRead)

+0

Dans le projet réel, il est multithread. Et je pense que Client.SendFile() est déjà implémenté en tant que mutithread. – OliverWho

+0

En fait, les AcceptAsync/ReadAsync/WriteAsync sont encore meilleurs, ils ont moins de frais généraux en réutilisant les objets d'état et ne lancent pas autant d'exceptions dans des situations standard. – Zarat

+0

@OliverWho Il a commenté le code que vous avez posté. Si vous avez d'autres codes que vous souhaitez consulter, publiez-les. – EJP

Questions connexes