C#高性能大容量SOCKET并发:SocketAsyncEventArgs

一、SocketAsyncEventArgs介绍

        SocketAsyncEventArgs是微软提供的高性能异步Socket实现类,主要为高性能网络服务器应用程序而设计,主要是为了避免在在异步套接字 I/O 量非常大时发生重复的对象分配和同步。使用此类执行异步套接字操作的模式包含以下步骤:
1.分配一个新的 SocketAsyncEventArgs 上下文对象,或者从应用程序池中获取一个空闲的此类对象。
2.将该上下文对象的属性设置为要执行的操作(例如,完成回调方法、数据缓冲区、缓冲区偏移量以及要传输的最大数据量)。
3.调用适当的套接字方法 (xxxAsync) 以启动异步操作。
4.如果异步套接字方法 (xxxAsync) 返回 true,则在回调中查询上下文属性来获取完成状态。
5.如果异步套接字方法 (xxxAsync) 返回 false,则说明操作是同步完成的。 可以查询上下文属性来获取操作结果。
6.将该上下文重用于另一个操作,将它放回到应用程序池中,或者将它丢弃。

二、具体实现

1、接收连接

public void StartAccept(SocketAsyncEventArgs acceptEventArg)
        {
            if (acceptEventArg == null)
            {
                acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnectedCompleted);
            }
            else
            {
                acceptEventArg.AcceptSocket = null;
            }
    
            maxClient.WaitOne();
            if (!socket.AcceptAsync(acceptEventArg))
            {
                ProcessAccept(acceptEventArg);
            }
        }

        //远端地址连接本地成功的回调
        public void OnConnectedCompleted(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.SocketError != SocketError.Success) 
                return;       //异步处理失败,不做处理

            SocketAsyncEventArgs saea = rwPool.Pop();
            AsyncUserToken token = saea.UserToken as AsyncUserToken;
            token.UserSocket = e.AcceptSocket;       //获取远端对话Socket对象
            string ipRemote = token.UserSocket.RemoteEndPoint.ToString();
            string ip = token.UserSocket.RemoteEndPoint.ToString();
            Console.WriteLine(string.Format("远程地址[{0}]成功连接到本地ip{1}", ipRemote, ip));

            SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs();
            sendArgs.RemoteEndPoint = token.UserSocket.RemoteEndPoint;
            sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
            sendArgs.UserToken = saea.UserToken;
            dicSAEA.TryAdd(token.UserSocket.RemoteEndPoint.ToString(), sendArgs);
            if (!e.AcceptSocket.ReceiveAsync(saea))
            {
                OnReceiveCompleted(saea);
            }

            StartAccept(e);
        }

2、接收客户端信息

private void OnReceiveCompleted(SocketAsyncEventArgs e)
        {
            if (e.SocketError != SocketError.Success) 
            {
                CloseClientSocket(e);
                Console.WriteLine("断开连接");
                return;
            }
            if (e.SocketError != SocketError.Success) 
                return;   //判断消息的接收状态
            AsyncUserToken token = e.UserToken as AsyncUserToken;
            int lengthBuffer = e.BytesTransferred;      //获取接收的字节长度
            string ipAddress = token.UserSocket.RemoteEndPoint.ToString();
            MessageFormat msg = new MessageFormat();
            //如果接收的字节长度为0,则判断远端服务器关闭连接
            if (lengthBuffer <= 0)
            {
                msg.msgStr = "远端服务器已经断开连接";
                msg.ip = ipAddress;
                Console.WriteLine(msg.msgStr);  
                CloseClientSocket(e);
            }
            else
            {
                byte[] receiveBuffer = e.Buffer;
                byte[] buffer = new byte[lengthBuffer];
                Buffer.BlockCopy(receiveBuffer, 0, buffer, 0, lengthBuffer);
                msg.msgStr = Encoding.UTF8.GetString(buffer);
                msg.ip = ipAddress;
                if (!token.UserSocket.ReceiveAsync(e))//继续异步接收消息
                {
                    OnReceiveCompleted(e);
                }
                Console.WriteLine("接收消息:" + msg.msgStr);

                SendAsync(msg);  //测试接收消息后立即返回给客户端
            }
        }

三、工程代码:服务端和客户端下载

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一零壹0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值