1

正如我们所知,.Net 有 UdpClient 用于 UDP 的简单 Socket 使用。

来自 MSDN:

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

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

还要别的吗?

谢谢

4

3 回答 3

4

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

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

于 2010-02-24T02:19:04.040 回答
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());
            }

        }
    }
}

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

于 2011-01-19T06:14:42.483 回答
0

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

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

希望这会有所帮助,最好的问候,汤姆。

于 2010-02-23T17:10:07.227 回答