C# Socket三种异步模型使用

在网络编程中,异步Socket模型主要用于处理高并发连接或避免阻塞线程。C#中有几种常见的异步Socket模型,每种模型都有其特定的用例和适用场景。以下是几种常见的异步Socket模型:

1. 基于回调的异步Socket模型

      C#中的Socket类提供了一组异步方法,如BeginAcceptBeginConnectBeginReceiveBeginSend,这些方法使用回调函数来处理异步操作。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;


public class AsynchronousSocketListener
{
    private static ManualResetEvent allDone = new ManualResetEvent(false);


    public static void StartListening()
    {
        byte[] bytes = new Byte[1024];
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
        Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);


        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(100);


            while (true)
            {
                allDone.Reset();
                Console.WriteLine("Waiting for a connection...");
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                allDone.WaitOne();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


    public static void AcceptCallback(IAsyncResult ar)
    {
        allDone.Set();
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);
        StateObject state = new StateObject();
        state.workSocket = handler;
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    }


    public static void ReadCallback(IAsyncResult ar)
    {
        String content = String.Empty;
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;
        int bytesRead = handler.EndReceive(ar);


        if (bytesRead > 0)
        {
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
            content = state.sb.ToString();
            if (content.IndexOf("<EOF>") > -1)
            {
                Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
            }
            else
            {
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            }
        }
    }


    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }


    public static void Main(String[] args)
    {
        StartListening();
    }
}


2. 基于async/await的异步Socket模型

        使用C#的异步编程模型,Socket类提供了一组Task返回的异步方法,如AcceptAsyncConnectAsyncReceiveAsyncSendAsync

 
 
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;


public class AsyncSocketServer
{
    public static async Task StartServerAsync()
    {
        IPAddress ipAddress = IPAddress.Loopback;
        int port = 11000;
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);


        Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);


        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(100);


            while (true)
            {
                Console.WriteLine("Waiting for a connection...");
                Socket handler = await listener.AcceptAsync();
                _ = Task.Run(() => HandleClientAsync(handler));
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


    private static async Task HandleClientAsync(Socket handler)
    {
        byte[] buffer = new byte[1024];
        try
        {
            while (true)
            {
                int bytesRead = await handler.ReceiveAsync(buffer, SocketFlags.None);
                if (bytesRead == 0)
                {
                    break;
                }
                string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Received : {0}", data);
                byte[] msg = Encoding.ASCII.GetBytes("Server Echo: " + data);
                await handler.SendAsync(msg, SocketFlags.None);
            }
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


    public static void Main(String[] args)
    {
        StartServerAsync().GetAwaiter().GetResult();
    }
}

3. 基于事件的异步Socket模型(适用于高级需求)

有时,你可能会使用SocketAsyncEventArgs类来处理更复杂的异步I/O操作。这个模型通常用于需要高度可扩展性的服务器。

 
 
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;


public class SocketAsyncEventArgsServer
{
    private static Socket _listenerSocket;
    private const int Port = 11000;


    public static void Main()
    {
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Loopback, Port);
        _listenerSocket = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp);


        _listenerSocket.Bind(localEndPoint);
        _listenerSocket.Listen(100);


        StartAccept(null);


        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();
    }


    private static void StartAccept(SocketAsyncEventArgs acceptEventArg)
    {
        if (acceptEventArg == null)
        {
            acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
        }
        else
        {
            acceptEventArg.AcceptSocket = null;
        }


        bool willRaiseEvent = _listenerSocket.AcceptAsync(acceptEventArg);
        if (!willRaiseEvent)
        {
            ProcessAccept(acceptEventArg);
        }
    }


    private static void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
    {
        ProcessAccept(e);
    }


    private static void ProcessAccept(SocketAsyncEventArgs e)
    {
        Socket s = e.AcceptSocket;
        Console.WriteLine("Client connected.");


        // Set up to receive data from the client.
        SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs();
        readEventArgs.SetBuffer(new byte[1024], 0, 1024);
        readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
        readEventArgs.UserToken = s;


        bool willRaiseEvent = s.ReceiveAsync(readEventArgs);
        if (!willRaiseEvent)
        {
            ProcessReceive(readEventArgs);
        }


        // Accept the next connection request.
        StartAccept(e);
    }


    private static void IO_Completed(object sender, SocketAsyncEventArgs e)
    {
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Receive:
                ProcessReceive(e);
                break;
            case SocketAsyncOperation.Send:
                ProcessSend(e);
                break;
        }
    }


    private static void ProcessReceive(SocketAsyncEventArgs e)
    {
        Socket s = (Socket)e.UserToken;
        if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
        {
            byte[] receivedData = new byte[e.BytesTransferred];
            Array.Copy(e.Buffer, receivedData, e.BytesTransferred);
            string receivedText = Encoding.ASCII.GetString(receivedData);
            Console.WriteLine("Received : {0}", receivedText);


            // Echo the data back to the client.
            e.SetBuffer(receivedData, 0, receivedData.Length);
            bool willRaiseEvent = s.SendAsync(e);
            if (!willRaiseEvent)
            {
                ProcessSend(e);
            }
        }
        else
        {
            s.Close();
        }
    }


    private static void ProcessSend(SocketAsyncEventArgs e)
    {
        Socket s = (Socket)e.UserToken;
        bool willRaiseEvent = s.ReceiveAsync(e);
        if (!willRaiseEvent)
        {
            ProcessReceive(e);
        }
    }
}

选择适合的异步Socket模型

  • 基于回调的异步Socket模型:适用于需要较高控制的场景,但代码可能会变得复杂且难以维护。

  • 基于async/await的异步Socket模型:推荐用于现代C#编程,代码简洁且易于维护。

  • 基于事件的异步Socket模型:适用于高性能和高并发的服务器应用,需要复杂的连接和I/O管理。

根据你的具体需求和应用场景,选择适合的异步Socket模型来实现高效的网络编程。

14448a42109c346a66108657f495db30.png

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值