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"));
                    }
                });
            }
        }
    }
}

 

posted @ 2015-03-20 17:35  排骨虾  阅读(1013)  评论(0编辑  收藏  举报