冠冕堂皇

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

SocketAsyncEventArgs是.net提供的关于异步socket类,封装了IOCP的使用,可以用它方便的实现NIO(non-blocking IO)

NIO对于提升某些场景下Server性能和吞吐量有很大益处,准备在服务框架中使用它来编写简易rpc的部分

微软官方的demo代理有所缺少:

http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

还有篇老外写的补充了缺少的代码:

http://www.codeproject.com/KB/IP/socketasynceventargssampl.aspx

不过例子还是感觉复杂了点,我只是需要知道SocketAsyncEventArgs本身如何使用而已,于是自行简化了一下:

 using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
     
    namespace SocketAsyncServer
    {
        public static class Program
        {
            public static void Main(String[] args)
            {
                IPAddress[] addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
                new TcpListener().Listen(new IPEndPoint(addressList[addressList.Length - 1], 9900));
     
                Console.ReadKey();
            }
        }
     
        public class TcpListener
        {
            private SocketAsyncEventArgs Args;
            private Socket ListenerSocket;
            private StringBuilder buffers;
            public TcpListener() { }
            public void Listen(EndPoint e)
            {
                //buffer
                buffers = new StringBuilder();
                //socket
                ListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ListenerSocket.Bind(e);
                ListenerSocket.Listen(10);
                //异步socket事件
                Args = new SocketAsyncEventArgs();
                Args.Completed += new EventHandler<SocketAsyncEventArgs>(ProcessAccept);
                BeginAccept(Args);
                Console.WriteLine("server run at {0}", e.ToString());
            }
     
            //开始接受
            void BeginAccept(SocketAsyncEventArgs e)
            {
                e.AcceptSocket = null;
                if (!ListenerSocket.AcceptAsync(e))
                    ProcessAccept(ListenerSocket, e);
            }
            //接受完毕 开始接收和发送
            void ProcessAccept(object sender, SocketAsyncEventArgs e)
            {
                Socket s = e.AcceptSocket;
                e.AcceptSocket = null;
     
                int bufferSize = 10;//1000 * 1024;
                var args = new SocketAsyncEventArgs();
                args.Completed += new EventHandler<SocketAsyncEventArgs>(OnIOCompleted);
                args.SetBuffer(new byte[bufferSize], 0, bufferSize);
                args.AcceptSocket = s;
                if (!s.ReceiveAsync(args))
                    this.ProcessReceive(args);
     
                BeginAccept(e);
            }
     
            //IOCP回调
            void OnIOCompleted(object sender, SocketAsyncEventArgs e)
            {
                switch (e.LastOperation)
                {
                    case SocketAsyncOperation.Receive:
                        this.ProcessReceive(e);
                        break;
                    case SocketAsyncOperation.Send:
                        this.ProcessSend(e);
                        break;
                    default:
                        throw new ArgumentException("The last operation completed on the socket was not a receive or send");
                }
            }
            
            //接收完毕
            void ProcessReceive(SocketAsyncEventArgs e)
            {
                if (e.BytesTransferred > 0)
                {
                    if (e.SocketError == SocketError.Success)
                    {
                        //读取
                        var data=Encoding.ASCII.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                        buffers.Append(data);
                        Console.WriteLine("Received:{0}", data);
     
                        if (e.AcceptSocket.Available == 0)
                        {
                            //读取完毕
                            Console.WriteLine("Receive Complete.Data:{0}", buffers.ToString());
                            //重置
                            buffers = new StringBuilder();
                            //发送反馈
                            Byte[] sendBuffer = Encoding.ASCII.GetBytes("result from server");
                          e.SetBuffer(sendBuffer, 0, sendBuffer.Length);
                          if (!e.AcceptSocket.SendAsync(e))
                          {
                     
                              this.ProcessSend(e);
                          }
                      }
                      else if (!e.AcceptSocket.ReceiveAsync(e))
                      {
                          this.ProcessReceive(e);
                      }
                  }
                  else
                  {
                      //this.ProcessError(e);
                  }
              }
              else
              {
                  //this.CloseClientSocket(e);
              }
          }
          //发送完毕
          void ProcessSend(SocketAsyncEventArgs e)
          {
              if (e.SocketError == SocketError.Success)
              {
   
                  if (!e.AcceptSocket.ReceiveAsync(e))
                  {
                      this.ProcessReceive(e);
                  }
              }
              else
              {
   
              }
          }
      }
       
  }
View Code

上述代码run起来之后,打开cmd用telnet测试下即可

telnet 127.0.0.1 9900

顺便推荐一下园子兄弟写的一个框架实现了nio的rpc

http://shuttler.codeplex.com/

http://www.cnblogs.com/overred/archive/2009/12/20/Shuttler_Net_2.html

posted on 2013-07-25 13:40  冠冕堂皇  阅读(512)  评论(0编辑  收藏  举报