【问题标题】:Why socket file transferring is slower than windows copy?为什么socket文件传输比windows复制慢?
【发布时间】:2012-04-13 17:15:10
【问题描述】:

我遇到了关于网络文件传输的问题。 当客户端超过 1 个时,Socket TCP/UDP 上传比本地 windows 复制慢。

我有一些 1Gbps 网络的 PC。

这是 Windows 复制案例。

一个客户端从服务器拷贝,最大上传速度100mbps左右。 (应该高于100mbps,路由有瓶颈。)

两个客户端从服务器复制,最大上传速度约为200mbps。

三个客户端从服务器复制,最大上传速度约300mbps。

这里是 Socket 案例。

一个客户端从服务器下载,最大上传速度100mbps左右。

两个客户端从服务器下载,最大上传速度约100mbps。

三个客户端从服务器下载,最大上传速度约100mbps。

如你所见,随着客户端数量的增加,socket服务器的上传速度并没有增加。

我们制作了一个简单的程序来测试这个问题。它遇到了同样的问题。 这只是非常简单的发送和接收调用。 请检查代码。

 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的家伙可以帮助我们。 谢谢高级。

【问题讨论】:

  • 取决于您的客户端/服务器实现,我们对此一无所知。因此这个问题无法回答。
  • 感谢快速回复,附上代码。
  • 您是否在与使用 windows 复制测试的情况下在同一台机器上运行代码?
  • 是的,与服务器相同的机器,相同的电脑。
  • 我怀疑您的代码甚至可以正常工作,因此测量它没有多大意义。您是 (a) 假设您在第一次读取时准确且仅获得了一个完整的文件名,这是无效的,并且 (b) 忽略了所有其他读取的结果,这也是无效的。您还按顺序传输到所有客户端,Windows 实用程序可以在其中并行执行。

标签: c# sockets networking tcpclient


【解决方案1】:

当然它更慢。您正在使用同一个线程来轮询所有客户端。

你应该切换到服务器中的异步方法(BeginRead/EndRead

【讨论】:

  • 实际项目中是多线程的。而且我认为 Client.SendFile() 已经实现为多线程。
  • 实际上 AcceptAsync/ReadAsync/WriteAsync 更好,它们通过重用状态对象来减少开销,并且在标准情况下不会抛出那么多异常。
  • @OliverWho 他评论了您发布的代码。如果您有其他需要审查的代码,请发布。
  • @Zarat:是的,它们更快,因为它们是根据 windows 使用的 IOCP 模型设计的。但是恕我直言,Begin/End 方法更容易使用,这对于像 OP 这样编码的人来说感觉更重要。
  • 是的,你是对的。如果用多线程实现会更快。多线程 UDP sendig 甚至比多线程 tcp 发送还要快。谢谢。
猜你喜欢
  • 2020-01-20
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2012-11-19
相关资源
最近更新 更多