SocketAsyncEventArgs里的AcceptSocket能独立存在吗?
独立存在是什么意思?
先来看一个例子.我们知道一个Socket对象(我们叫他ListenScoket)可以调用AcceptAsync并接受一个SocketAsyncEventArgs对象,如果操作成功则ListenSocket会为SocketAsyncEventArgs对象创建一个新的Socket对象(我们叫它AcceptSccket)。也就是这样
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);listenSocket.Bind(new IPEndPoint(IPAddress.Parse("10.175.5.172"), 60000));listenSocket.Listen(10);SocketAsyncEventArgs asyncEventArgs =new SocketAsyncEventArgs();asyncEventArgs.Completed += asyncEventArgs_Completed;listenSocket.AcceptAsync(asyncEventArgs);
如果ListenSocket关闭之后AcceptSocket还可以正常工作,那么我们就说AcceptSocket是独立存在的.
那到底AcceptSocket能否独存在呢?
首先我们来看AcceptSocket是什么时候创建的.其实当listenSocket.AcceptAsync(asyncEventArgs)执行的时候SocketAsyncEventArgs内部的AcceptSocket就已经被创建了,但是它不能被用来发送和接收数据.假如我们在AcceptAsync之后紧跟着调用AcceptSocket来发送一个”OK”字符串,那么会得到这样一个错误:
'asyncEventArgs.AcceptSocket.Send(ASCIIEncoding.ASCII.GetBytes("OK"))' threw an exception of type 'System.Net.Sockets.SocketException'
base: {"A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"}
ErrorCode: 10057
Message: "A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"
SocketErrorCode: NotConnected
注意错误消息中被标为红色的部分,这说明AcceptSocket对象已经创建了,不过没有可用的地址,也就是没有客户端IP和端口.这个很好理解,因为客户端还没有连接上呢.当客户端连接成功的时候,ListenSocket会将客户端的地址(IP和端口)赋予AcceptSocket.同时,SocketAsyncEventArgs的Completed事件会被触发,我们就知道AcceptSocket可以正常使用了.
为什么会有这个疑问呢? 在我们的应用中ListenSocket会创建很多的AcceptSocket, 某一个时刻我们想停止接收更多新的Socket连接,同时又想保持现有的连接,那么我们可以直接把ListenSocket关闭.经过测试是不需要担心AcceptSocket会受到影响的.也就是说AcceptSocket可以独立存在的. 下面是测试代码.
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace SocketAsyncEventArgsTest { class Program { static int socketCount = 0; static Socket listenSocket; static void Main(string[] args) { listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(new IPEndPoint(IPAddress.Parse("10.175.5.172"), 60000)); listenSocket.Listen(10); SocketAsyncEventArgs asyncEventArgs =new SocketAsyncEventArgs(); asyncEventArgs.Completed += asyncEventArgs_Completed; listenSocket.AcceptAsync(asyncEventArgs); SocketAsyncEventArgs asyncEventArgs2 = new SocketAsyncEventArgs(); asyncEventArgs2.Completed += asyncEventArgs_Completed; listenSocket.AcceptAsync(asyncEventArgs2); //listenSocket.Close(); Console.Read(); } static void asyncEventArgs_Completed(object sender, SocketAsyncEventArgs e) { if (SocketError.Success == e.SocketError) { socketCount++; if (2 == socketCount) // Close the listen socket will not close the accept sockets opened by it. // so the accept socket can continue receive/send data normally. listenSocket.Close(); Socket acceptSocket = e.AcceptSocket; byte[] buffer=new byte[1024]; Task.Factory.StartNew(() => { while(true) { acceptSocket.Receive(buffer); Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer)); acceptSocket.Send(ASCIIEncoding.ASCII.GetBytes("OK")); } }); } } } }