C# 为什么套接字文件传输比windows copy慢?

C# 为什么套接字文件传输比windows copy慢?,c#,sockets,networking,tcpclient,C#,Sockets,Networking,Tcpclient,我有一个关于网络文件传输的问题。 当客户端超过1个时,套接字TCP/UDP上载速度比本机windows copy慢 我有一些1Gbps网络的电脑 这是Windows复制案例 从服务器复制一个客户端,最大上载速度约为100mbps。(应该大于100mbps,线路有瓶颈) 两个客户端从服务器复制,最大上传速度约为200mbps 三个客户端从服务器复制,最大上传速度约为300mbps 这是插座盒 一个客户端从服务器下载,最大上传速度约为100mbps 两个客户端从服务器下载,最大上传速度约为100mb

我有一个关于网络文件传输的问题。 当客户端超过1个时,套接字TCP/UDP上载速度比本机windows copy慢

我有一些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;
           }
         }
      }
   }
 }
类程序
{
静态列表会话=新列表();
静态void Main(字符串[]参数)
{
bool-isServer=false;
Console.WriteLine(“作为服务器运行”(Y/N)”;
字符串answer=Console.ReadLine();
if(answer.ToUpper().StartsWith(“Y”))isServer=true;
如果(isServer)
{
TcpListener侦听器=新的TcpListener(IPAddress.Any,13579);
WriteLine(“侦听:”+((IPEndPoint)listener.LocalEndpoint.ToString());
listener.Start();
线程工作线程=新线程(()=>
{
while(true)
{
锁定(会话)
{
foreach(会话中的var客户端)
{
如果(client.Available>0)
{
byte[]buffer=新字节[client.Available];
int length=client.client.Receive(缓冲区);
stringfilepath=Encoding.UTF8.GetString(缓冲区,0,长度);
if(File.Exists(filePath))
{
foreach(会话中的var接收器)
receiver.Client.SendFile(filePath,null,null,TransmitFileOptions.UseKernelApc | TransmitFileOptions.WriteBehind);
}
}
}
} 
睡眠(200);
}
});
workerThread.IsBackground=true;
workerThread.Start();
while(true)
{
TcpClient client=listener.AcceptTcpClient();
锁定(会话)
{
会话。添加(客户端);
}
}
}
其他的
{
WriteLine(“输入服务器IP:”);
字符串ipAddress=Console.ReadLine();
TcpClient client=新的TcpClient(ipAddress,13579);
WriteLine(“输入远程服务器上的文件路径:”);
字符串remoteFilePath=Console.ReadLine();
如果(remoteFilePath!=“”)
client.client.Send(Encoding.UTF8.GetBytes(remoteFilePath));
字节[]recvBuffer=新字节[32768];
while(true)
{
尝试
{
client.client.Receive(recvBuffer,32768,SocketFlags.None);
}
捕获(SocketException e)
{
WriteLine(“传输中断:{0}”,e.Message);
打破
}
}
}
}
}
这阻碍了我们实现性能更好的套接字工具。 希望你们能帮我们。
谢谢你。当然要慢一点。您正在使用同一线程轮询所有客户端


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

取决于您的客户机/服务器实现,我们对此一无所知。因此,这个问题无法回答。感谢您的快速回复,附上代码。您是否在与windows copy测试相同的机器上运行代码?是的,与服务器相同的机器,相同的pc。我怀疑您的代码是否工作正常,因此还没有多少测量的意义。您是(a)假设您在第一次读取时获得的文件名完全正确且仅完整,这是无效的,(b)忽略所有其他读取的结果,这也是无效的。您还将按顺序传输到所有客户端,Windows实用程序可以在其中并行执行这些操作。在实际项目中,它是多线程的。我认为Client.SendFile()已经实现为多线程。实际上,AcceptSync/ReadAsync/WriteAsync甚至更好,它们通过重用状态对象减少了开销,并且在标准情况下不会引发那么多异常。@OliverWho对您发布的代码发表了评论。如果您还有其他代码需要审阅,请发布。@Zarat:是的,它们的速度更快,因为它们是按照windows使用的IOCP模型设计的。但是我认为开始/结束方法更容易使用,这对于像OP这样编写代码的人来说更重要。是的,你是对的。如果使用多线程实现,速度会更快。多线程UDP发送比多线程tcp发送更快。非常感谢。