2012-04-13 41 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