2012-04-13 19 views
0

ネットワークファイル転送に関する問題があります。 2つ以上のクライアントが存在する場合、ソケットTCP/UDPのアップロードがネイティブウィンドウのコピーより遅くなります。ソケットファイル転送がWindowsコピーよりも遅いのはなぜですか?

私は1Gbpsのネットワークを持ついくつかのPCを持っています。

ここにWindowsのコピーケースがあります。

サーバーからの1つのクライアントコピーでは、最大アップロード速度は約100mbpsです。 (100mbpsを超えると、経路にボトルネックが発生する)

2人のクライアントがサーバーからコピーすると、最大アップロード速度は約200mbpsになります。

3台のクライアントがサーバーからコピーした場合、最大アップロード速度は約300mbpsです。

ここにソケットケースがあります。

サーバーからのクライアントのダウンロードでは、最大アップロード速度は約100mbpsです。

2人のクライアントがサーバーからダウンロードすると、最大アップロード速度は約100mbpsです。

3人のクライアントがサーバーからダウンロードした場合、最大アップロード速度は約100mbpsです。

ご覧のとおり、クライアント数が増えても、ソケットサーバーのアップロード速度は向上しません。

この問題をテストする簡単なプログラムを作成しました。同じ問題が発生します。 非常に簡単なsendとrecvの呼び出しです。 コードを確認してください。

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

は、クライアント/サーバの実装に依存サーバー(BeginRead/EndRead)で非同期メソッドに切り替える必要があります。したがって、質問は答えが不可能です。 – jgauffin

+0

ありがとうございました。 – OliverWho

+0

Windowsコピーでテストする場合と同じマシンでコードを実行していますか? – nos

答えて

1

もちろん、それは遅いです。すべてのクライアントをポーリングするために同じスレッドを使用しています。

あなたは我々が何も知らない

+0

実際のプロジェクトでは、マルチスレッド化されています。そして、私はClient.SendFile()がすでにmutithreadとして実装されていると思います。 – OliverWho

+0

実際、AcceptAsync/ReadAsync/WriteAsyncはさらに優れているため、状態オブジェクトを再利用することによるオーバーヘッドが少なく、標準的な状況では多くの例外をスローしません。 – Zarat

+0

@Oliverあなたが投稿したコードに彼がコメントしました。レビューしたい他のコードがある場合は、投稿してください。 – EJP