zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/gmth/p/3214193.html
Copyright © 2011-2022 走看看