2012-04-13 78 views
0

我有關於網絡文件傳輸的問題。 當有多個客戶端時,套接字TCP/UDP上傳比本機窗口複製要慢。爲什麼socket文件傳輸比windows複製慢?

我有一些PC與1Gbps網絡。

這裏是Windows複製案例。

從服務器上覆制一個客戶端,最大上傳速度約爲100mbps。 (應該高於100Mbps,路由存在瓶頸。)

兩臺客戶端從服務器複製,最大上傳速度約爲200mbps。

三臺客戶端從服務器複製,最大上傳速度約爲300mbps。

這裏是套接字的情況。

一個客戶端從服務器下載,最大上傳速度約爲100mbps。

兩臺客戶端從服務器上下載,最大上傳速度約爲100mbps。

三臺客戶端從服務器下載,最大上傳速度約爲100mbps。

如您所見,套接字服務器上傳速度在客戶端數量增加時不會增加。

我們做了一個簡單的程序來測試這個問題。它遇到了同樣的問題。 這只是非常簡單的發送和接聽電話。 請檢查代碼。

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

這是阻止我們實現更好的性能插座工具。 希望stackoverflow的人可以幫助我們。 感謝先進。

+1

取決於你的客戶機/服務器實現,我們什麼都不知道。因此這個問題是不可能回答的。 – jgauffin 2012-04-13 08:53:49

+0

感謝您的快速回復,附上代碼。 – OliverWho 2012-04-13 09:12:31

+0

您是否正在使用Windows副本測試的相同機器上運行代碼? – nos 2012-04-13 09:18:29

回答

1

當然是慢的。您正在使用相同的線程來輪詢所有客戶端。

您應該切換到服務器(BeginRead/EndRead)異步方法

+0

在真實的項目中,它是多線程的。我認爲Client.SendFile()已經實現爲mutithread。 – OliverWho 2012-04-13 09:29:10

+0

實際上,AcceptAsync/ReadAsync/WriteAsync甚至更好,它們通過重用狀態對象的開銷更少,並且不會在標準情況下拋出儘可能多的異常。 – Zarat 2012-04-13 09:35:29

+0

@OliverWho他對你發佈的代碼發表了評論。如果你有一些你想要查看的其他代碼,請發佈。 – EJP 2012-04-13 09:58:59