• 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. CentOS 7上安装gitlab-runner

    1.yum install gitlab-runner -y 2.Registering Runners a.Run the following command: gitlab-runner regi ...

  2. 关于结构体内存对齐方式的总结(#pragma pack()和alignas())

    最近闲来无事,翻阅msdn,在预编译指令中,翻阅到#pragma pack这个预处理指令,这个预处理指令为结构体内存对齐指令,偶然发现还有另外的内存对齐指令aligns(C++11),__declsp ...

  3. 【Codeforces Round #425 (Div. 2) A】Sasha and Sticks

    [Link]: [Description] [Solution] 傻逼题; 获取n/k; 对n/k的奇偶性讨论一下就好 [NumberOf WA] 0 [Reviw] [Code] #include ...

  4. Android.mk脚本推断文件是否存在

    Android.mk 推断文件是否存在,若存在则复制该文件到某个文件夹 $(shell test -f [文件] && echo yes)的值假设是yes, 则文件存在,然后进行she ...

  5. tsp问题——遗传算法解决

    TSP问题最简单的求解方法是枚举法. 它的解是多维的.多局部极值的.趋于无穷大的复杂解的空间.搜索空间是n个点的全部排列的集合.大小为(n-1)! .能够形象地把解空间看成是一个无穷大的丘陵地带,各山 ...

  6. Android ScrollView滚动实现大众点评、网易云音乐评论悬停效果

    今天听着网易云音乐,写着代码,真是爽翻了. http://blog.csdn.net/linshijun33/article/details/47910833 网易云音乐这个产品亮点应该在评论这一模块 ...

  7. centos配置tomcat编辑修改

    https://jingyan.baidu.com/article/6525d4b1382f0aac7d2e9421.html

  8. Json应用案例

    Json应用案例之FastJson   这几天在网上找关于Json的一些案例,无意当中找到了一个我个人感觉比较好的就是阿里巴巴工程师写的FastJson. package com.jerehedu.f ...

  9. myBatis通过逗号分隔字符串,foreach

    前言 当数据库里存储的值是以逗号分隔格式存储的字符串时. 数据格式如下:  id name  ids   1  张三  a,b,c  2  李四  c,d,e 我们拿到的条件参数是:b,e 1.后台通 ...

  10. Java中join和yield的作用

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 1.   A.join,在API中的解释是,堵塞当前线程B,直到A执行完毕并死掉,再执行B. 用一个 ...