data.Length);//设置发送数据//e.SetBuffer(data

时间:2022-05-15 09:02:36

我一直在探寻一个高性能的Socket客户端代码。以前,我使用Socket类写了一些基于传统异步编程模型的代码(BeginSend、BeginReceive,等等)也看过很多博客的常识,在linux中有poll和epoll来实现,在windows下面
微软MSDN中也供给了SocketAsyncEventArgs这个类来实现IOCP 地点:https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx
NET Framework中的APM也称为Begin/End模式。这是因为会挪用Begin要领来启动异步操纵,然后返回一个IAsyncResult 东西。可以选择将一个代办代理作为参数供给给Begin要领,异步操纵完成时会挪用该要领。或者,一个线程可以期待 IAsyncResult.AsyncWaitHandle。当回调被挪用或发出期待信号时,就会挪用End要领来获取异步操纵的功效。这种模式很灵活,使用相对简单,在 .NET Framework 中非每每见。
但是,您必需注意,如果进行大量异步套接字操纵,是要支付价钱的。针对每次操纵,都必需创建一个IAsyncResult东西,而且该东西不能被反复使用。由于大量使用东西分配和垃圾收集,这会影响性能。为了解决这个问题,新版本供给了另一个使用套接字上执行异步I/O的要领模式。这种新模式并不要求为每个套接字操纵分配操纵上下文东西。

代码下载: 这里的代码优化了的

方针

在上面微软供给的例子我感受不是很完整,没有具体一个流程,只是受到客户端动静后发送不异内容给客户端,初学者不容易看懂流程,因为我花了一天的时间来实现一个成果齐全的IOCP处事器,

效果如下

data.Length);//设置发送数据//e.SetBuffer(data

代码

首先是ICOPServer.cs 这个类是IOCP处事器的核心类,目前这个类是网络上对照全的代码,MSDN上面的例子都没有我的全

[csharp]

using System; 

using System.Collections.Generic; 

using System.Linq; 

using System.Text; 

using System.Net.Sockets; 

using System.Net; 

using System.Threading; 

namespace ServerTest 

/// <summary>

/// IOCP SOCKET处事器

/// </summary>

public class IOCPServer : IDisposable 

    { 

const int opsToPreAlloc = 2; 

        #region Fields

/// <summary>

/// 处事器措施允许的最大客户端连接数

/// </summary>

private int _maxClient; 

/// <summary>

/// 监听Socket,用于接受客户真个连接请求

/// </summary>

private Socket _serverSock; 

/// <summary>

/// 当前的连接的客户端数

/// </summary>

private int _clientCount; 

/// <summary>

/// 用于每个I/O Socket操纵的缓冲区巨细

/// </summary>

private int _bufferSize = 1024; 

/// <summary>

/// 信号量

/// </summary>

        Semaphore _maxAcceptedClients; 

/// <summary>

/// 缓冲区打点

/// </summary>

        BufferManager _bufferManager; 

/// <summary>

/// 东西池

/// </summary>

        SocketAsyncEventArgsPool _objectPool; 

private bool disposed = false; 

        #endregion

        #region Properties

/// <summary>

/// 处事器是否正在运行

/// </summary>

public bool IsRunning { get; private set; } 

/// <summary>

/// 监听的IP地点

/// </summary>

public IPAddress Address { get; private set; } 

/// <summary>

/// 监听的端口

/// </summary>

public int Port { get; private set; } 

/// <summary>

/// 通信使用的编码

/// </summary>

public Encoding Encoding { get; set; } 

        #endregion

        #region Ctors

/// <summary>

/// 异步IOCP SOCKET处事器

/// </summary>

/// <param>监听的端口</param>

/// <param>最大的客户端数量</param>

public IOCPServer(int listenPort,int maxClient) 

            : this(IPAddress.Any, listenPort, maxClient) 

        { 

        } 

/// <summary>

/// 异步Socket TCP处事器

/// </summary>

/// <param>监听的终结点</param>

/// <param>最大客户端数量</param>

public IOCPServer(IPEndPoint localEP, int maxClient) 

            : this(localEP.Address, localEP.Port,maxClient) 

        { 

        } 

/// <summary>

/// 异步Socket TCP处事器

/// </summary>

/// <param>监听的IP地点</param>

/// <param>监听的端口</param>

/// <param>最大客户端数量</param>

public IOCPServer(IPAddress localIPAddress, int listenPort, int maxClient) 

        { 

this.Address = localIPAddress; 

this.Port = listenPort; 

this.Encoding = Encoding.Default; 

            _maxClient = maxClient; 

            _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 

            _bufferManager = new BufferManager(_bufferSize * _maxClient * opsToPreAlloc,_bufferSize); 

            _objectPool = new SocketAsyncEventArgsPool(_maxClient); 

            _maxAcceptedClients = new Semaphore(_maxClient, _maxClient);  

        } 

        #endregion

        #region 初始化

/// <summary>

/// 初始化函数

/// </summary>

public void Init() 

        { 

// Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds

// against memory fragmentation

            _bufferManager.InitBuffer(); 

// preallocate pool of SocketAsyncEventArgs objects

            SocketAsyncEventArgs readWriteEventArg; 

for (int i = 0; i < _maxClient; i++) 

            { 

//Pre-allocate a set of reusable SocketAsyncEventArgs

                readWriteEventArg = new SocketAsyncEventArgs(); 

                readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnIOCompleted); 

                readWriteEventArg.UserToken = null; 

// assign a byte buffer from the buffer pool to the SocketAsyncEventArg object

                _bufferManager.SetBuffer(readWriteEventArg); 

// add SocketAsyncEventArg to the pool

                _objectPool.Push(readWriteEventArg); 

            } 

        } 

        #endregion

        #region Start

/// <summary>

/// 启动

/// </summary>

public void Start() 

        { 

if (!IsRunning) 

            { 

                Init(); 

                IsRunning = true; 

                IPEndPoint localEndPoint = new IPEndPoint(Address, Port); 

// 创建监听socket

                _serverSock = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 

//_serverSock.ReceiveBufferSize = _bufferSize;

//_serverSock.SendBufferSize = _bufferSize;

if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6) 

                { 

// 配置监听socket为 dual-mode (IPv4 & IPv6)

// 27 is equivalent to IPV6_V6ONLY socket option in the winsock snippet below,