C# SocketAsyncEventArgs类

  • 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构造函数。

    1 // Implements the connection logic for the socket server. (实现套字节服务器的链接逻辑) 2 // After accepting a connection, all data read from the client (链接后在客户端读取所有数据) 3 // is sent back to the client. The read and echo back to the client pattern () 4 // is continued until the client disconnects.(在接受连接之后,从客户端读取的所有数据都被发送回客户端。继续读取和回传客户端模式,直到客户端断开连接。) 5 class Server 6 { 7 private int m_numConnections; // the maximum number of connections the sample is designed to handle simultaneously (样本被设计为同时处理的最大连接数) 8 private int m_receiveBufferSize;// buffer size to use for each socket I/O operation (用于每个套接字I/O操作的缓冲区大小) 9 BufferManager m_bufferManager; // represents a large reusable set of buffers for all socket operations(表示用于所有套接字操作的大型可重用缓冲区集合) 10 const int opsToPreAlloc = 2; // read, write (don't alloc buffer space for accepts)读写,不分配缓存空间来接受 11 Socket listenSocket; // the socket used to listen for incoming connection requests(用于侦听传入连接请求的套接字) 12 // pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations(可重用SocketAsyncEventArgs对象池,用于编写、读取和接受套接字操作) 13 SocketAsyncEventArgsPool m_readWritePool; 14 int m_totalBytesRead; // counter of the total # bytes received by the server(服务器接收的总字节数的计数器) 15 int m_numConnectedSockets; // the total number of clients connected to the server (连接到服务器的客户端总数) 16 Semaphore m_maxNumberAcceptedClients;//接受客户的最大数 17 18 // Create an uninitialized server instance. 19 // To start the server listening for connection requests 20 // call the Init method followed by Start method 21 //(创建一个未初始化的服务器实例。要启动服务器侦听连接请求,请调用init方法,然后使用start方法。) 22 // <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously(本被设计为同时处理的最大连接数)</param> 23 // <param name="receiveBufferSize">buffer size to use for each socket I/O operation(用于每个套接字I/O操作的缓冲区大小)</param> 24 public Server(int numConnections, int receiveBufferSize) 25 { 26 m_totalBytesRead = 0; 27 m_numConnectedSockets = 0; 28 m_numConnections = numConnections; 29 m_receiveBufferSize = receiveBufferSize; 30 // allocate buffers such that the maximum number of sockets can have one outstanding read and 31 //write posted to the socket simultaneously (分配缓冲区,使套接字的最大数量可以同时将一个优秀的读写写入到套接字中。) 32 m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc, 33 receiveBufferSize); 34 35 m_readWritePool = new SocketAsyncEventArgsPool(numConnections); 36 m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); 37 } 38 39 // Initializes the server by preallocating reusable buffers and 40 // context objects. These objects do not need to be preallocated 41 // or reused, but it is done this way to illustrate how the API can 42 // easily be used to create reusable objects to increase server performance. 43 //(通过预先分配可重用的缓冲区和上下文对象初始化服务器。这些对象不需要预先分配或重用,而是通过这种方式来说明API是如何容易地被用来创建可重用对象以提高服务器性能的。) 44 public void Init() 45 { 46 // Allocates one large byte buffer which all I/O operations use a piece of. This gaurds 47 // against memory fragmentation(分配一个大字节缓冲区,所有I/O操作都使用一个。这是反对记忆碎片的) 48 m_bufferManager.InitBuffer(); 49 50 // preallocate pool of SocketAsyncEventArgs objects 预分配的对象池 51 SocketAsyncEventArgs readWriteEventArg; 52 53 for (int i = 0; i < m_numConnections; i++) 54 { 55 //Pre-allocate a set of reusable SocketAsyncEventArgs 56 readWriteEventArg = new SocketAsyncEventArgs(); 57 readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); 58 readWriteEventArg.UserToken = new AsyncUserToken(); 59 60 // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object(指定从缓冲池字节缓冲区的socketasynceventarg对象) 61 m_bufferManager.SetBuffer(readWriteEventArg); 62 63 // add SocketAsyncEventArg to the pool 64 m_readWritePool.Push(readWriteEventArg); 65 } 66 67 } 68 69 // Starts the server such that it is listening for 70 // incoming connection requests. 71 // 72 // <param name="localEndPoint">The endpoint which the server will listening 73 // for connection requests on</param> 74 public void Start(IPEndPoint localEndPoint) 75 { 76 // create the socket which listens for incoming connections 77 listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 78 listenSocket.Bind(localEndPoint); 79 // start the server with a listen backlog of 100 connections 80 listenSocket.Listen(100); 81 82 // post accepts on the listening socket 83 StartAccept(null); 84 85 //Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount); 86 Console.WriteLine("Press any key to terminate the server process...."); 87 Console.ReadKey(); 88 } 89 90 91 // Begins an operation to accept a connection request from the client 92 // 93 // <param name="acceptEventArg">The context object to use when issuing 94 // the accept operation on the server's listening socket</param> 95 public void StartAccept(SocketAsyncEventArgs acceptEventArg) 96 { 97 if (acceptEventArg == null) 98 { 99 acceptEventArg = new SocketAsyncEventArgs(); 100 acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed); 101 } 102 else 103 { 104 // socket must be cleared since the context object is being reused 105 acceptEventArg.AcceptSocket = null; 106 } 107 108 m_maxNumberAcceptedClients.WaitOne(); 109 bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg); 110 if (!willRaiseEvent) 111 { 112 ProcessAccept(acceptEventArg); 113 } 114 } 115 116 // This method is the callback method associated with Socket.AcceptAsync 117 // operations and is invoked when an accept operation is complete 118 // 119 void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) 120 { 121 ProcessAccept(e); 122 } 123 124 private void ProcessAccept(SocketAsyncEventArgs e) 125 { 126 Interlocked.Increment(ref m_numConnectedSockets); 127 Console.WriteLine("Client connection accepted. There are {0} clients connected to the server", 128 m_numConnectedSockets); 129 130 // Get the socket for the accepted client connection and put it into the 131 //ReadEventArg object user token 132 SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop(); 133 ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket; 134 135 // As soon as the client is connected, post a receive to the connection 136 bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs); 137 if(!willRaiseEvent){ 138 ProcessReceive(readEventArgs); 139 } 140 141 // Accept the next connection request 142 StartAccept(e); 143 } 144 145 // This method is called whenever a receive or send operation is completed on a socket 146 // 147 // <param name="e">SocketAsyncEventArg associated with the completed receive operation</param> 148 void IO_Completed(object sender, SocketAsyncEventArgs e) 149 { 150 // determine which type of operation just completed and call the associated handler 151 switch (e.LastOperation) 152 { 153 case SocketAsyncOperation.Receive: 154 ProcessReceive(e); 155 break; 156 case SocketAsyncOperation.Send: 157 ProcessSend(e); 158 break; 159 default: 160 throw new ArgumentException("The last operation completed on the socket was not a receive or send"); 161 } 162 163 } 164 165 // This method is invoked when an asynchronous receive operation completes. 166 // If the remote host closed the connection, then the socket is closed. 167 // If data was received then the data is echoed back to the client. 168 // 169 private void ProcessReceive(SocketAsyncEventArgs e) 170 { 171 // check if the remote host closed the connection 172 AsyncUserToken token = (AsyncUserToken)e.UserToken; 173 if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) 174 { 175 //increment the count of the total bytes receive by the server 176 Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); 177 Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead); 178 179 //echo the data received back to the client 180 e.SetBuffer(e.Offset, e.BytesTransferred); 181 bool willRaiseEvent = token.Socket.SendAsync(e); 182 if (!willRaiseEvent) 183 { 184 ProcessSend(e); 185 } 186 187 } 188 else 189 { 190 CloseClientSocket(e); 191 } 192 } 193 194 // This method is invoked when an asynchronous send operation completes. 195 // The method issues another receive on the socket to read any additional 196 // data sent from the client 197 // 198 // <param name="e"></param> 199 private void ProcessSend(SocketAsyncEventArgs e) 200 { 201 if (e.SocketError == SocketError.Success) 202 { 203 // done echoing data back to the client 204 AsyncUserToken token = (AsyncUserToken)e.UserToken; 205 // read the next block of data send from the client 206 bool willRaiseEvent = token.Socket.ReceiveAsync(e); 207 if (!willRaiseEvent) 208 { 209 ProcessReceive(e); 210 } 211 } 212 else 213 { 214 CloseClientSocket(e); 215 } 216 } 217 218 private void CloseClientSocket(SocketAsyncEventArgs e) 219 { 220 AsyncUserToken token = e.UserToken as AsyncUserToken; 221 222 // close the socket associated with the client 223 try 224 { 225 token.Socket.Shutdown(SocketShutdown.Send); 226 } 227 // throws if client process has already closed 228 catch (Exception) { } 229 token.Socket.Close(); 230 231 // decrement the counter keeping track of the total number of clients connected to the server 232 Interlocked.Decrement(ref m_numConnectedSockets); 233 m_maxNumberAcceptedClients.Release(); 234 Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets); 235 236 // Free the SocketAsyncEventArg so they can be reused by another client 237 m_readWritePool.Push(e); 238 } 239 240 }

    待续

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid

C# SocketAsyncEventArgs类 - HelloWorld