【问题标题】:The performance (or other) differences between raw Socket and UdpClient?原始 Socket 和 UdpClient 之间的性能(或其他)差异?
【发布时间】:2010-02-23 16:51:09
【问题描述】:

我们知道 .Net 有 UdpClient 用于 UDP 的简单 Socket 使用。

来自 MSDN:

如果您正在编写一个相对简单的应用程序并且不需要最高性能,请考虑使用 TcpClient、TcpListener 和 UdpClient。这些类为 Socket 通信提供了一个更简单、对用户更友好的接口。

我想知道 Raw Socket 和 UdpClient 之间的性能差异有多大?我知道 UdpClient 是 Udp 的套接字包装器,它没有异步读/写。

还有什么?

谢谢

【问题讨论】:

  • 对我来说,UdpClient/Socket 之间的区别在于能够重用接收缓冲区/使用我的缓冲区是 Socket。当您收到大量 Udp 数据包以尽量减少分配时,这一点很重要。

标签: performance sockets udpclient


【解决方案1】:

正如文档所说,UdpClient/TcpClient 是 Socket 类之上的一个瘦包装器。如果您只想发送/接收数据块,那么这些类就很好。对于这种场景,Socket 和 UdpClient/TcpClient 的性能没有区别。

但是,Socket 确实以 XXXAsync() 方法的形式提供了一种更快的 IO 方式。这些方法允许您进行非常快速的 I/O,并且不会暴露在 TcpClient/UdpClient 中。这就是文档所说的“性能差异”的意思——为了获得更快的性能,您必须深入研究 Socket 类并使用这些方法 (XXXAsync)。

【讨论】:

    【解决方案2】:

    sendfile 并不快。

    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Net.Cache;
    using System.Threading;
    
    namespace socket_sendfile
    {
        delegate TimeSpan SendFileDelegate(Socket client, String filename, long fileSize);
    
        class Header
        {
            public long FileSize { get; set; }
            public int FileNumber { get; set; }
    
            public void Serialize(Stream stream)
            {
                byte[] buffer = BitConverter.GetBytes(this.FileNumber);
                stream.Write(buffer, 0, buffer.Length);
    
                buffer = BitConverter.GetBytes(this.FileSize);
                stream.Write(buffer, 0, buffer.Length);
            }
    
            public static Header Deserialize(Stream stream)
            {
                Header header = new Header();
    
                byte[] buffer = new byte[4];
                int read = stream.Read(buffer, 0, buffer.Length);
                header.FileNumber = BitConverter.ToInt32(buffer, 0);
    
                buffer = new byte[sizeof(long)];
                read = stream.Read(buffer, 0, buffer.Length);
                header.FileSize = BitConverter.ToInt64(buffer, 0);
                return header;
            }
        }
    
        class Program
        {
            private Random rand = new Random();
    
            static void Main(string[] args)
            {
                Program prog = new Program();
    
                try
                {
                    prog.StartServer();
    
                    using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                    {
                        client.Bind(new IPEndPoint(0, 0));
                        client.Connect(new IPEndPoint(IPAddress.Loopback, 8080));
    
                        prog.Run(client, new SendFileDelegate(prog.SendFile1));
    
                        Console.WriteLine();
                        prog.Run(client, new SendFileDelegate(prog.SendFile2));
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);
                }
                Console.ReadKey();
            }
    
            void StartServer()
            {
                Thread serverThread = new Thread(new ThreadStart(this.Server));
                serverThread.Start();
            }
    
            void Run(Socket client, SendFileDelegate sendFileMethod)
            {
                foreach (long size in this.GetNextSize())
                {
                    String filename = Path.GetTempFileName();
    
                    this.CreateFile(filename, size);
    
                    for (int i = 0; i  GetNextSize()
            {
                ulong[] sizes = { 1024, 4096, 8192, 16385, 65536, 1048576 };
                for (int i = 0; i  0)
                    {
                        rand.NextBytes(buffer);
                        int writeSize = buffer.Length;
                        if (writeSize > (int)remaining)
                        {
                            writeSize = (int)remaining;
                        }
    
                        bw.Write(buffer, 0, writeSize);
                        remaining -= writeSize;
                    }
                }
            }
    
            TimeSpan SendFile1(Socket client, String filename, long fileSize)
            {
                Stopwatch timer = new Stopwatch();
    
                //timer.Start();
                using (NetworkStream ns = new NetworkStream(client))
                {
                    Header header = new Header();
                    header.FileSize = fileSize;
                    header.FileNumber = 1;
    
                    // send the header
                    header.Serialize(ns);
    
                    using (FileStream fs = File.OpenRead(filename))
                    {
                        //byte[] buffer = new byte[1024];
                        byte[] buffer = new byte[fileSize];
                        int read = fs.Read(buffer, 0, buffer.Length);
                        //Console.WriteLine("read = " + read);
    
                        while (read > 0)
                        {
                            timer.Start();
                            ns.Write(buffer, 0, read);
                            timer.Stop();
                            read = fs.Read(buffer, 0, buffer.Length);
                            //Console.WriteLine("read = " + read);
                        }
                    }
                }
    
                //timer.Stop();
    
                return timer.Elapsed;
            }
    
            TimeSpan SendFile2(Socket client, String filename, long fileSize)
            {
                Stopwatch timer = new Stopwatch();
    
                //timer.Start();
                using (NetworkStream ns = new NetworkStream(client))
                {
                    Header header = new Header();
                    header.FileSize = fileSize;
                    header.FileNumber = 1;
    
                    byte[] headerBuffer = null;
                    using (MemoryStream ms = new MemoryStream())
                    {
                        header.Serialize(ms);
                        ms.Seek(0, SeekOrigin.Begin);
                        headerBuffer = ms.ToArray();
                    }
    
                    // send the header
                    timer.Start();
                    client.SendFile(filename, headerBuffer, null, TransmitFileOptions.UseDefaultWorkerThread);
                    timer.Stop();
                }
    
                //timer.Stop();
    
                return timer.Elapsed;
            }
    
            void Server()
            {
                byte[] buffer = new byte[1024];
                try
                {
                    TcpListener listener = new TcpListener(IPAddress.Loopback, 8080);
                    listener.Start();
                    using (TcpClient client = listener.AcceptTcpClient())
                    using (NetworkStream ns = client.GetStream())
                    {
                        bool hasData = true;
                        while (hasData)
                        {
                            // first get the header. Header has the file size.
                            Header header = Header.Deserialize(ns);
    
                            long remaining = header.FileSize;
    
                            while (remaining > 0)
                            {
                                int readSize = buffer.Length;
                                if ((long)readSize > remaining)
                                    readSize = (int)remaining;
    
                                int read = ns.Read(buffer, 0, readSize);
                                remaining -= read;
                            }
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
    
            }
        }
    }
    

    浪费了我几个小时的宝贵时间。

    【讨论】:

      【解决方案3】:

      UDP 是一种零错误检查的无连接协议,它是与 TCP 的权衡,它比 TCP 更快。与 TCP 相比,将 UDP 视为一种即发即弃协议,其中完整性和校验和是 TCP 相对于 UDP 的额外开销。

      无论使用何种协议,RawSocket 都没有影响或差异。 RawSocket 只是原始的,您必须放入相关的标头,例如源/目标 IP 地址,并确保标头符合相关协议。它与套接字的速度无关——这当然取决于您选择的协议。

      希望这会有所帮助, 最好的祝福, 汤姆。

      【讨论】:

      • @tommieb75:我的意思是原始套接字就像 Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.UDP);如果我使用上面的语句使用UDP而不是使用Udpclient,那么性能差异是什么??? .Net说有
      • 您不能将 Stream 与 UDP 一起使用。它会给出 SocketException。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 1970-01-01
      • 2010-11-21
      • 2012-05-26
      • 2013-09-02
      • 2014-03-15
      相关资源
      最近更新 更多