• SocketAsyncEventArgs


    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

  • 相关阅读:
    hdu 1032 水题也wrong 两次(于是乎更有刷水题的必要了)
    淘宝刷钻员
    hdu 4006 求第K大的数 优先队列
    骗子满天飞
    hdu 2115 :I Love This Game(Presentation Error容易输出wrong)
    hdu 1048 (map的使用)
    hdu 1722 数论题
    hdu 1237 简单计算器
    Android编码规范
    xamarin开发实例(一) android PC 基于Tcp双向通信
  • 原文地址:https://www.cnblogs.com/gmth/p/3214193.html
Copyright © 2020-2023  润新知