原始Socket和UdpClient之间的性能(或其他)差异?

时间:2010-02-23 16:51:10

标签: performance sockets udpclient

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

来自MSDN:

  

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

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

还有别的吗?

由于

3 个答案:

答案 0 :(得分:4)

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

但是,Socket确实以XXXAsync()方式提供了一种更快的IO方式。这些方法允许您执行非常快速的I / O,并且不会在TcpClient / UdpClient中公开。这就是文档所说的“性能差异” - 对于更快的性能,你必须深入研究Socket类并使用这些方法(XXXAsync)。

答案 1 :(得分:4)

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());
            }

        }
    }
}

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

答案 2 :(得分:0)

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

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

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