• Namespace:System.Net.Sockets
  • Assemblies:System.Net.Sockets.dll, System.dll, netstandard.dll
  • (Represents an asynchronous socket operation)代表一个异步套接字操作:
  • public class SocketAsyncEventArgs : EventArgs, IDisposable
    Inheritance(继承) Object->EventArgs->SocketAsyncEventArgs
    Implements(实现) IDisposable

    实例

    下面的代码示例实现连接逻辑使用套接字服务器socketasynceventargs类接受连接后,从客户端读取所有数据发送回客户端。读和回声返回到客户端模式直到客户端断开连接。缓冲管理器类,通过这个例子,用于在代码示例显示SetBuffer(Byte[], Int32, Int32)方法的socketasynceventargspool类,本例中使用的是在代码示例显示socketasynceventargs构造函数。

    // Implements the connection logic for the socket server. (实现套字节服务器的链接逻辑)
    // After accepting a connection, all data read from the client (链接后在客户端读取所有数据)
    // is sent back to the client. The read and echo back to the client pattern ()
    // is continued until the client disconnects.(在接受连接之后,从客户端读取的所有数据都被发送回客户端。
    继续读取和回传客户端模式,直到客户端断开连接。)
    class Server
    {
    private int m_numConnections; // the maximum number of connections the sample is designed to handle simultaneously (样本被设计为同时处理的最大连接数)
    private int m_receiveBufferSize;// buffer size to use for each socket I/O operation (用于每个套接字I/O操作的缓冲区大小)
    BufferManager m_bufferManager; // represents a large reusable set of buffers for all socket operations(表示用于所有套接字操作的大型可重用缓冲区集合)
    const int opsToPreAlloc = ; // read, write (don't alloc buffer space for accepts)读写,不分配缓存空间来接受
    Socket listenSocket; // the socket used to listen for incoming connection requests(用于侦听传入连接请求的套接字)
    // pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations(可重用SocketAsyncEventArgs对象池,用于编写、读取和接受套接字操作)
    SocketAsyncEventArgsPool m_readWritePool;
    int m_totalBytesRead; // counter of the total # bytes received by the server(服务器接收的总字节数的计数器)
    int m_numConnectedSockets; // the total number of clients connected to the server (连接到服务器的客户端总数)
    Semaphore m_maxNumberAcceptedClients;//接受客户的最大数 // Create an uninitialized server instance.
    // To start the server listening for connection requests
    // call the Init method followed by Start method
    //(创建一个未初始化的服务器实例。要启动服务器侦听连接请求,请调用init方法,然后使用start方法。)
    // <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously(本被设计为同时处理的最大连接数)</param>
    // <param name="receiveBufferSize">buffer size to use for each socket I/O operation(用于每个套接字I/O操作的缓冲区大小)</param>
    public Server(int numConnections, int receiveBufferSize)
    {
    m_totalBytesRead = ;
    m_numConnectedSockets = ;
    m_numConnections = numConnections;
    m_receiveBufferSize = receiveBufferSize;
    // allocate buffers such that the maximum number of sockets can have one outstanding read and
    //write posted to the socket simultaneously (分配缓冲区,使套接字的最大数量可以同时将一个优秀的读写写入到套接字中。)
    m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc,
    receiveBufferSize); m_readWritePool = new SocketAsyncEventArgsPool(numConnections);
    m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
    } // Initializes the server by preallocating reusable buffers and
    // context objects. These objects do not need to be preallocated
    // or reused, but it is done this way to illustrate how the API can
    // easily be used to create reusable objects to increase server performance.
    //(通过预先分配可重用的缓冲区和上下文对象初始化服务器。这些对象不需要预先分配或重用,而是通过这种方式来说明API是如何容易地被用来创建可重用对象以提高服务器性能的。)
    public void Init()
    {
    // Allocates one large byte buffer which all I/O operations use a piece of. This gaurds
    // against memory fragmentation(分配一个大字节缓冲区,所有I/O操作都使用一个。
    这是反对记忆碎片的)
    m_bufferManager.InitBuffer(); // preallocate pool of SocketAsyncEventArgs objects 预分配的对象池
    SocketAsyncEventArgs readWriteEventArg; for (int i = ; i < m_numConnections; i++)
    {
    //Pre-allocate a set of reusable SocketAsyncEventArgs
    readWriteEventArg = new SocketAsyncEventArgs();
    readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
    readWriteEventArg.UserToken = new AsyncUserToken(); // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object(指定从缓冲池字节缓冲区的socketasynceventarg对象)
    m_bufferManager.SetBuffer(readWriteEventArg); // add SocketAsyncEventArg to the pool
    m_readWritePool.Push(readWriteEventArg);
    } } // Starts the server such that it is listening for
    // incoming connection requests.
    //
    // <param name="localEndPoint">The endpoint which the server will listening
    // for connection requests on</param>
    public void Start(IPEndPoint localEndPoint)
    {
    // create the socket which listens for incoming connections
    listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    listenSocket.Bind(localEndPoint);
    // start the server with a listen backlog of 100 connections
    listenSocket.Listen(); // post accepts on the listening socket
    StartAccept(null); //Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount);
    Console.WriteLine("Press any key to terminate the server process....");
    Console.ReadKey();
    } // Begins an operation to accept a connection request from the client
    //
    // <param name="acceptEventArg">The context object to use when issuing
    // the accept operation on the server's listening socket</param>
    public void StartAccept(SocketAsyncEventArgs acceptEventArg)
    {
    if (acceptEventArg == null)
    {
    acceptEventArg = new SocketAsyncEventArgs();
    acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
    }
    else
    {
    // socket must be cleared since the context object is being reused
    acceptEventArg.AcceptSocket = null;
    } m_maxNumberAcceptedClients.WaitOne();
    bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
    if (!willRaiseEvent)
    {
    ProcessAccept(acceptEventArg);
    }
    } // This method is the callback method associated with Socket.AcceptAsync
    // operations and is invoked when an accept operation is complete
    //
    void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
    {
    ProcessAccept(e);
    } private void ProcessAccept(SocketAsyncEventArgs e)
    {
    Interlocked.Increment(ref m_numConnectedSockets);
    Console.WriteLine("Client connection accepted. There are {0} clients connected to the server",
    m_numConnectedSockets); // Get the socket for the accepted client connection and put it into the
    //ReadEventArg object user token
    SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
    ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket; // As soon as the client is connected, post a receive to the connection
    bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
    if(!willRaiseEvent){
    ProcessReceive(readEventArgs);
    } // Accept the next connection request
    StartAccept(e);
    } // This method is called whenever a receive or send operation is completed on a socket
    //
    // <param name="e">SocketAsyncEventArg associated with the completed receive operation</param>
    void IO_Completed(object sender, SocketAsyncEventArgs e)
    {
    // determine which type of operation just completed and call the associated handler
    switch (e.LastOperation)
    {
    case SocketAsyncOperation.Receive:
    ProcessReceive(e);
    break;
    case SocketAsyncOperation.Send:
    ProcessSend(e);
    break;
    default:
    throw new ArgumentException("The last operation completed on the socket was not a receive or send");
    } } // This method is invoked when an asynchronous receive operation completes.
    // If the remote host closed the connection, then the socket is closed.
    // If data was received then the data is echoed back to the client.
    //
    private void ProcessReceive(SocketAsyncEventArgs e)
    {
    // check if the remote host closed the connection
    AsyncUserToken token = (AsyncUserToken)e.UserToken;
    if (e.BytesTransferred > && e.SocketError == SocketError.Success)
    {
    //increment the count of the total bytes receive by the server
    Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred);
    Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead); //echo the data received back to the client
    e.SetBuffer(e.Offset, e.BytesTransferred);
    bool willRaiseEvent = token.Socket.SendAsync(e);
    if (!willRaiseEvent)
    {
    ProcessSend(e);
    } }
    else
    {
    CloseClientSocket(e);
    }
    } // This method is invoked when an asynchronous send operation completes.
    // The method issues another receive on the socket to read any additional
    // data sent from the client
    //
    // <param name="e"></param>
    private void ProcessSend(SocketAsyncEventArgs e)
    {
    if (e.SocketError == SocketError.Success)
    {
    // done echoing data back to the client
    AsyncUserToken token = (AsyncUserToken)e.UserToken;
    // read the next block of data send from the client
    bool willRaiseEvent = token.Socket.ReceiveAsync(e);
    if (!willRaiseEvent)
    {
    ProcessReceive(e);
    }
    }
    else
    {
    CloseClientSocket(e);
    }
    } private void CloseClientSocket(SocketAsyncEventArgs e)
    {
    AsyncUserToken token = e.UserToken as AsyncUserToken; // close the socket associated with the client
    try
    {
    token.Socket.Shutdown(SocketShutdown.Send);
    }
    // throws if client process has already closed
    catch (Exception) { }
    token.Socket.Close(); // decrement the counter keeping track of the total number of clients connected to the server
    Interlocked.Decrement(ref m_numConnectedSockets);
    m_maxNumberAcceptedClients.Release();
    Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets); // Free the SocketAsyncEventArg so they can be reused by another client
    m_readWritePool.Push(e);
    } }

    待续

C# SocketAsyncEventArgs类的更多相关文章

  1. [转帖]译文:如何使用SocketAsyncEventArgs类(How to use the SocketAsyncEventArgs class)

    原文链接:http://norke.blog.163.com/blog/static/276572082011828104315941/ 引言 我一直在探寻一个高性能的Socket客户端代码.以前,我 ...

  2. 译文:如何使用SocketAsyncEventArgs类(How to use the SocketAsyncEventArgs class)

      转载自: http://blog.csdn.net/hulihui/article/details/3244520 原文:How to use the SocketAsyncEventArgs c ...

  3. c# SocketAsyncEventArgs类的使用 IOCP服务器

    要编写高性能的Socket服务器,为每个接收的Socket分配独立的处理线程的做法是不可取的,当连接数量很庞大时,服务器根本无法应付.要响应庞大的连接数量,需要使用IOCP(完成端口)来撤换并处理响应 ...

  4. 转 C#高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

    原创性申明 本文作者:小竹zz  博客地址:http://blog.csdn.net/zhujunxxxxx/article/details/43573879转载请注明出处引言 我一直在探寻一个高性能 ...

  5. C#高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

    网址:http://blog.csdn.net/zhujunxxxxx/article/details/43573879 引言 我一直在探寻一个高性能的Socket客户端代码.以前,我使用Socket ...

  6. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  7. C# - 网络编程 之 Socket

    命名空间 using System.Net; using System.Net.Socket; Socket类 初始化 public socket (AddressFamily addressFami ...

  8. Windows Phone下的Socket编程

    讨论下有关于Windows Phone下的Socket编程方面的知识. Socket就是通常所称的套接字,用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过Socket向网络发出请求或者应答 ...

  9. HL AsySocket 服务开发框架 - 总体思路与架构

    一 背景 最近在园子了浏览了几篇有关Socket文章,得到了一些启发萌生了想要重构公司在2000年用.NET Framework 2.0 与 Visual Studio 2005开发的AsySocke ...

随机推荐

  1. Linux学习总结(8)——VMware v12.1.1 专业版以及永久密钥

    VMware v12.1.1 专业版以及永久密钥 热门虚拟机软件VMware Workstation 现已更新至v12.1.1 专业版!12.0属于大型更新,专门为Win10的安装和使用做了优化,支持 ...

  2. Your Ruby version is 2.2.3, but your Gemfile specified 2.2.2

    在文章 Ruby On Rails中REST API使用演示样例--基于云平台+云服务打造自己的在线翻译工具 中,从Bluemix上下载的初始Hello World演示样例代码在本地环境下运行调试时提 ...

  3. Qt Installer Framework的学习(二)

    Qt Installer Framework的学习(二) Qt Installer Framework的一些操作能够使用最常见的Qt项目来表示,也就是说,书写pro文件,使用qmake执行之,除了能够 ...

  4. VS添加程序集

    项目->添加->引用->程序集 可在项目的引用目录中,查看引用的程序集

  5. 7.cocos精灵创建和绘制

    创建Layer层的类 T2LayerSprite.h #pragma once #include "cocos2d.h" USING_NS_CC; class T2LayerSpr ...

  6. IIS文件上传大小修改配置说明

    原因:Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值(IIS 7 默认文件上传大小时30M). 解决:IIS7更改asp.net文件上传大小限制 步骤如下: 1.    修改I ...

  7. BZOJ 4582 贪心

    思路: 显然是个贪心 排个序 然后扫几遍就好了 (重叠的区间不能取) //By SiriusRen #include <cstdio> #include <algorithm> ...

  8. HDU 2689 Tree

    Tree Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. Windows学习总结(2)——30+ Windows命令提示符快捷键汇总

    即便你平时经常用到 Windows 命令提示符,可能也会对本文将提到的快捷键数量感到惊讶.其实我们可以使用快捷键来简化命令提示符中的选择操作,或对文本进行重复操作,下面我们会列出完整列表. 大家都知道 ...

  10. 洛谷 P1358 扑克牌

    P1358 扑克牌 题目描述 组合数学是数学的重要组成部分,是一门研究离散对象的科学,它主要研究满足一定条件的组态(也称组合模型)的存在.计数以及构造等方面的问题.组合数学的主要内容有组合计数.组合设 ...