/*----------------------------------------------------------------------------------------------
 
       Copyright (C) DHCC 版权所有

       系统名:
       类  名:  SocketManager
       概  要: 
       创建者:  Hu Ha
       创建日:  01/18/2010 13:59:23
       履  历:    No.        日期           Ver.No        修改人             描述																																																																										

------------------------------------------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Platform.Common.LogSystem;

namespace TellerSystem.Communication.SocketListener
{
    public delegate TResult Func<TResult>();

    /// <summary>
    /// 提供套接字管理
    /// </summary>
    public class SocketManager : IDisposable
    {
        //监听端口字典
        private Dictionary<int, Socket> m_ListenningSockets;

        private static object Locker = new object();
        private BufferManager m_BufferManager;
        //阈值
        private int m_ThresholdValue = 102400;

        #region 属性定义

        private bool m_SuspendAllSend;

        /// <summary>
        /// 暂停所有数据发送
        /// </summary>
        public bool SuspendAllSend
        {
            get { return m_SuspendAllSend; }
            set
            {
                //如果为true,通知发送线程继续等待
                if (value)
                    this.m_SendControl.Reset();
                else//所有发送线程继续发送
                    this.m_SendControl.Set();

                m_SuspendAllSend = value;
            }
        }

        private bool m_StopAllSend;

        /// <summary>
        /// 停止所有数据发送
        /// </summary>
        public bool StopAllSend
        {
            get { return m_StopAllSend; }
            set
            {
                if (value && this.SuspendAllSend)
                {
                    //通知发送线程继续
                    this.SuspendAllSend = false;
                }
                m_StopAllSend = value;
            }
        }

        private int m_MaxListenningRequest;

        private ManualResetEvent m_SendControl;

        /// <summary>
        /// 获取最大监听请求数
        /// </summary>
        public int MaxListenningRequest
        {
            get { return m_MaxListenningRequest; }
        }

        private int m_SendBufferSize;

        /// <summary>
        /// 获取或设置发送缓冲区大小
        /// </summary>
        public int SendBufferSize
        {
            get { return m_SendBufferSize; }
            set { m_SendBufferSize = value; }
        }
        private int m_ReceiveBufferSize;

        /// <summary>
        /// 获取或设置接收缓冲区大小
        /// </summary>
        public int ReceiveBufferSize
        {
            get { return m_ReceiveBufferSize; }
            set { m_ReceiveBufferSize = value; }
        }
        private int m_SendTimeOut;

        /// <summary>
        /// 获取或设置发送超时时间
        /// </summary>
        public int SendTimeOut
        {
            get { return m_SendTimeOut; }
            set { m_SendTimeOut = value; }
        }
        private int m_ReceiveTimeOut;

        /// <summary>
        /// 获取或设置接收超时时间
        /// </summary>
        public int ReceiveTimeOut
        {
            get { return m_ReceiveTimeOut; }
            set { m_ReceiveTimeOut = value; }
        }

        /// <summary>
        /// 获取阈值，当接收完数据如果没有达到这个阈值，则此次socket会话所接收的数据会
        /// 一次性的传递给接收事件，而不会收到了接收buffer大小就触发一次事件。所以这个
        /// 值必须大于或等于接收buffer的大小
        /// </summary>
        public int ThresholdValue
        {
            get { return m_ThresholdValue; }
        }

        #endregion

        #region 事件定义

        /// <summary>
        /// 开始监听时发生
        /// </summary>
        public event EventHandler<ServerPortEventArgs> ServerStart;

        /// <summary>
        /// 停止监听时发生
        /// </summary>
        public event EventHandler<ServerPortEventArgs> ServerStop;

        /// <summary>
        /// 开始发送时发生
        /// </summary>
        public event EventHandler SendStart;

        /// <summary>
        /// 发送完成后发生
        /// </summary>
        public event EventHandler SendCompleted;

        /// <summary>
        /// 正在接收数据发生
        /// </summary>
        public event EventHandler<DataReceivedEventArgs> DataReceived;

        /// <summary>
        /// 正在发送时发生
        /// </summary>
        public event EventHandler<DataSendEventArgs> Sending;

        /// <summary>
        /// 发生Socket错误时发生
        /// </summary>
        public event EventHandler<SocketErrorEventArgs> ErrorHappened;

        #endregion

        public SocketManager()
            : this(200, 12400, 0, 0, 0)
        {

        }

        /// <summary>
        /// 用相关信息初始化SocketManager
        /// </summary>
        /// <param name="maxClientCount">最大侦听连接数</param>
        /// <param name="receiveBufferSize">接收缓冲区大小</param>
        /// <param name="sendBufferSize">发送缓冲区大小</param>
        /// <param name="receiveTimeOut">接收超时时间(单位为毫秒,0为不超时)</param>
        /// <param name="sendTimeOut">发送超时时间(单位为毫秒,0为不超时)</param>
        public SocketManager(int maxClientCount, int receiveBufferSize, int sendBufferSize, int receiveTimeOut, int sendTimeOut)
        {
            this.m_MaxListenningRequest = maxClientCount;
            this.m_SendBufferSize = sendBufferSize;
            this.m_ReceiveBufferSize = receiveBufferSize;
            this.m_SendTimeOut = sendTimeOut;
            this.m_ReceiveTimeOut = receiveTimeOut;
            this.m_BufferManager = new BufferManager(maxClientCount, receiveBufferSize, sendBufferSize);
            this.m_SendControl = new ManualResetEvent(true);
            this.m_ListenningSockets = new Dictionary<int, Socket>();
        }

        #region 监听

        /// <summary>
        /// 监听指定端口号
        /// </summary>
        /// <param name="port">监听端口号</param>
        /// <returns>监听是否成功</returns>
        public bool StartListenning(int port)
        {
            return this.StartListenning(port, true);
        }

        /// <summary>
        /// 监听指定端口号
        /// </summary>
        /// <param name="port">监听端口号</param>
        /// <param name="async">是否异步接收:true为异步，false为同步</param>
        /// <returns>监听是否成功</returns>
        public bool StartListenning(int port, bool async)
        {
            Socket socket = this.GetSocket(0, 0);

            try
            {
                if (!socket.IsBound)
                {
                    lock (Locker)
                    {
                        //double  check
                        if (!socket.IsBound)
                        {
                            //uint IOC_IN = 0x80000000;
                            //uint IOC_VENDOR = 0x18000000;
                            //uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
                            //socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, new byte[4]);
                            // socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                            //socket.Bind(new IPEndPoint(Dns.GetHostAddresses(Environment.MachineName)[0], port));
                            socket.Bind(GetIpv4EndPoint(port));
                            socket.Listen(this.m_MaxListenningRequest);
                            this.m_ListenningSockets.Add(port, socket);
                            this.OnServerStart(port);
                            this.StartReceive(socket, async);
                        }
                    }
                }
            }
            catch (SocketException se)
            {
                socket.Close();
                this.OnErrorHappened(se, SocketOperation.Bind);
                return false;
            }

            return true;
        }

        /// <summary>
        /// 批量监听端口号
        /// </summary>
        /// <param name="ports">端口集合</param>
        public void StartListenningBatch(int[] ports)
        {
            foreach (int port in ports)
            {
                this.StartListenning(port);
            }
        }

        /// <summary>
        /// 停止监听
        /// </summary>
        public void StopListenning(bool onlyCloseSocket)
        {
            Dictionary<int, Socket> dic = new Dictionary<int, Socket>(this.m_ListenningSockets);

            this.m_ListenningSockets.Clear();

            foreach (KeyValuePair<int, Socket> kvp in dic)
            {
                kvp.Value.Close();
                this.OnServerStop(kvp.Key);
            }

            if (!onlyCloseSocket)
            {
                this.m_BufferManager.Clear();
                this.m_SendControl.Close();
            }
        }

        #endregion

        #region 发送

        /// <summary>
        /// 发生数据到指定主机端口
        /// </summary>
        /// <param name="hostNameOrAddress">主机名或主机IP地址</param>
        /// <param name="port">对方端口号</param>
        /// <param name="data">待发送数据</param>
        public void Send(string hostNameOrAddress, int port, byte[] data)
        {
            this.Send(hostNameOrAddress, port, data, true);
        }

        /// <summary>
        /// 发生数据到指定主机端口
        /// </summary>
        /// <param name="hostNameOrAddress">主机名或主机IP地址</param>
        /// <param name="port">对方端口号</param>
        /// <param name="data">待发送数据</param>
        /// <param name="async">是否异步发送:true为异步，false为同步</param>
        public void Send(string hostNameOrAddress, int port, byte[] data, bool async)
        {
            if (data == null)
            {
                throw new ArgumentNullException("发送数据不能为空");
            }

            //EndPoint endPoint = this.GetEndPoint(hostNameOrAddress, port);
            EndPoint endPoint = GetIpv4EndPoint(hostNameOrAddress, port);

            this.Send(endPoint, data, async);
        }

        /// <summary>
        /// Sends the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="endPoint">The end point.</param>
        /// <param name="async">if set to <c>true</c> [async].</param>
        public void Send(EndPoint endPoint, byte[] data, bool async)
        {
            if (data == null)
            {
                throw new ArgumentNullException("发送数据不能为空");
            }

            Socket socket = this.GetSocket(this.m_SendTimeOut, 0);

            try
            {
                this.OnSendStart();

                if (async)
                {
                    SendAsync(socket, endPoint, data);
                }
                else
                {
                    SendSynchronize(socket, endPoint, data);
                }

            }
            catch (SocketException se)
            {
                socket.Close();
                this.OnErrorHappened(se, SocketOperation.Connect);
            }
        }

        /// <summary>
        /// 同步发送数据
        /// </summary>
        /// <param name="socket">发送用socket</param>
        /// <param name="endPoint">远程终结点</param>
        /// <param name="data">待发送数据</param>
        private void SendSynchronize(Socket socket, EndPoint endPoint, byte[] data)
        {
            socket.Connect(endPoint);

            SendDataInternal(socket, data);
        }

        /// <summary>
        /// 开始发送数据
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="data"></param>
        private void SendDataInternal(Socket socket, byte[] data)
        {
            SocketError socketError;

            socket.Send(data, 0, data.Length, SocketFlags.None, out socketError);

            try
            {
                socket.Shutdown(SocketShutdown.Both);
            }
            catch (SocketException ex)
            {
                socketError = ex.SocketErrorCode;
            }

            socket.Close();

            this.FireSendEvents(socketError);
        }

        /// <summary>
        /// 异步发送数据
        /// </summary>
        /// <param name="socket">发送用socket</param>
        /// <param name="endPoint">远程终结点<</param>
        /// <param name="data">待发送数据<</param>
        private void SendAsync(Socket socket, EndPoint endPoint, byte[] data)
        {
            socket.BeginConnect(endPoint, delegate(IAsyncResult ar)
            {
                try
                {
                    socket.EndConnect(ar);
                }
                catch (SocketException se)
                {
                    socket.Close();
                    this.OnErrorHappened(se, SocketOperation.Connect);
                    return;
                }

                this.SendDataInternal(socket, data);

            }, null);
        }

        /// <summary>
        ///  发送数据
        /// </summary>
        /// <param name="hostNameOrAddress">主机名或主机IP地址</param>
        /// <param name="port">对方端口号</param>
        /// <param name="dataGetterFunc">数据获取器</param>
        /// <remarks>
        ///    这个方法为发送大数据而准备,并且强制为异步发送
        /// </remarks>
        public void Send(string hostNameOrAddress, int port, Func<byte[]> dataGetterFunc)
        {
            if (dataGetterFunc == null) return;

            //EndPoint endPoint = this.GetEndPoint(hostNameOrAddress, port);

            EndPoint endPoint = GetIpv4EndPoint(hostNameOrAddress, port);

            this.Send(endPoint, dataGetterFunc);
        }

        /// <summary>
        /// Sends the specified end point.
        /// </summary>
        /// <param name="endPoint">The end point.</param>
        /// <param name="dataGetterFunc">The data getter func.</param>
        public void Send(EndPoint endPoint, Func<byte[]> dataGetterFunc)
        {
            if (endPoint == null)
            {
                throw new ArgumentNullException("远程终结点不能为空");
            }

            Socket sendSocket = this.GetSocket(this.SendTimeOut, 0);

            this.OnSendStart();

            try
            {
                //开始异步连接远程主机
                sendSocket.BeginConnect(endPoint, delegate(IAsyncResult ar)
                {
                    try
                    {
                        sendSocket.EndConnect(ar);
                    }
                    catch (SocketException se)
                    {
                        this.OnErrorHappened(se, SocketOperation.Connect);
                        sendSocket.Close();
                        return;
                    }

                    AsyncCallback callback = this.GetSendCallback(sendSocket, dataGetterFunc);

                    this.SendDataInternal(sendSocket, callback, dataGetterFunc);

                }, null);
            }
            catch (SocketException se)
            {
                sendSocket.Close();
                this.OnErrorHappened(se, SocketOperation.Connect);
            }

        }

        /// <summary>
        /// 获取异步发送回调
        /// </summary>
        /// <param name="sendSocket">发送套接字</param>
        /// <param name="dataGetterFunc">数据获取器</param>
        /// <returns>异步发送回调</returns>
        private AsyncCallback GetSendCallback(Socket sendSocket, Func<byte[]> dataGetterFunc)
        {
            AsyncCallback callback = null;

            callback = delegate(IAsyncResult receiveResult)
            {
                SocketError socketError;

                int sendLength = sendSocket.EndSend(receiveResult, out socketError);

                if (socketError == SocketError.Success)
                {
                    this.OnSending(sendLength);

                    //继续发送
                    this.SendDataInternal(sendSocket, callback, dataGetterFunc);
                }
                else
                {
                    this.FireSendEvents(socketError);
                    sendSocket.Shutdown(SocketShutdown.Both);
                    sendSocket.Close();
                }
            };

            return callback;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sendSocket">发送套接字</param>
        /// <param name="callback">异步发送回调</param>
        /// <param name="dataGetterFunc">数据获取器</param>
        private void SendDataInternal(Socket sendSocket, AsyncCallback callback, Func<byte[]> dataGetterFunc)
        {
            if (m_SuspendAllSend)
            {
                this.m_SendControl.WaitOne();
            }

            //从数据获取器中获取数据
            byte[] data = dataGetterFunc();

            if (this.m_StopAllSend)
            {
                sendSocket.Close();
                return;
            }

            SocketError socketError = SocketError.Success;
            //如果数据为空则表明数据获取器已经获取完全部数据，清理资源
            if (data == null || data.Length == 0)
            {
                this.FireSendEvents(socketError);
                sendSocket.Close();
                return;
            }

            //开始发送
            sendSocket.BeginSend(data, 0, data.Length, SocketFlags.None, out socketError, callback, null);

            if (socketError != SocketError.Success)
            {
                this.FireSendEvents(socketError);
                sendSocket.Close();
            }
        }

        /// <summary>
        /// 根据SocketError触发相应事件
        /// </summary>
        /// <param name="socketError">socket错误代码</param>
        private void FireSendEvents(SocketError socketError)
        {
            if (socketError == SocketError.Success)
            {
                this.OnSendCompleted();
            }
            else
            {
                this.OnErrorHappened(new SocketException((int)socketError), SocketOperation.Send);
            }
        }

        #endregion

        #region 接收

        /// <summary>
        /// 开始接收数据
        /// </summary>
        /// <param name="listenningSocket">监听套接字</param>
        /// <param name="async">是否异步接收:true为异步，false为同步</param>
        private void StartReceive(Socket listenningSocket, bool async)
        {
            try
            {
                if (async)
                {
                    this.ReceiveAsync(listenningSocket);
                }
                else
                {
                    this.ReceiveSynchronize(listenningSocket);
                }
            }
            catch (SocketException se)
            {
                this.OnErrorHappened(se, SocketOperation.Receive);
            }
        }

        /// <summary>
        /// 同步接收指定端口数据
        /// </summary>
        /// <param name="socket"></param>
        private void ReceiveSynchronize(Socket socket)
        {
            Socket receiveSocket = socket.Accept();

            this.ReceiveDataInternal(receiveSocket, false);

            //持续接受请求
            this.ReceiveSynchronize(socket);
        }

        /// <summary>
        /// 同步接收数据
        /// </summary>
        /// <param name="receiveSocket">接收套接字</param>
        /// <param name="bufferBlockIndex">当前接收缓冲区在整个接收缓冲区的索引</param>
        /// <param name="receiveBufferOffset">当前接收缓冲区在整个接收缓冲区的偏移量</param>
        /// <param name="id">唯一标识此次接收</param>
        private void ReceiveSynchronize(Socket receiveSocket, byte[] buffer, int bufferBlockIndex, int receiveBufferOffset, string guid, bool conditionCompleted)
        {
            SocketError socketError;

            //开始同步接收
            int receiveLength = receiveSocket.Receive(this.m_BufferManager.ReceiveBuffer,
                                                      receiveBufferOffset,
                                                      this.m_BufferManager.ReceiveBufferSize,
                                                      SocketFlags.None, out socketError);

            if (socketError == SocketError.Success)
            {
                if (receiveLength > 0)
                {
                    conditionCompleted = this.ProcessReceivedData(ref buffer, receiveLength,
                        receiveBufferOffset, conditionCompleted, guid, receiveSocket.RemoteEndPoint);

                    this.ReceiveSynchronize(receiveSocket, buffer, bufferBlockIndex, receiveBufferOffset, guid, conditionCompleted);
                }
                else
                {
                    this.OnReceived(buffer, guid, receiveSocket.RemoteEndPoint, true);
                    this.ClearReceiveInfo(receiveSocket, bufferBlockIndex);
                }
            }
            else
            {
                this.ClearReceiveInfo(receiveSocket, bufferBlockIndex);
                this.OnErrorHappened(new SocketException((int)socketError), SocketOperation.Receive);
            }
        }

        /// <summary>
        /// 异步接收指定端口数据
        /// </summary>
        /// <param name="socket">The socket.</param>
        private void ReceiveAsync(Socket socket)
        {
            AsyncCallback callback = GetAcceptCallback(socket);

            this.BeginAccept(socket, callback);
        }

        /// <summary>
        /// 开始接收socket请求
        /// </summary>
        /// <param name="socket">接收socket请求的socket</param>
        /// <param name="callback">接受请求回调</param>
        private void BeginAccept(Socket socket, AsyncCallback callback)
        {
            try
            {
                //开始接受请求
                socket.BeginAccept(callback, null);
            }
            catch (SocketException se)
            {
                this.OnErrorHappened(se, SocketOperation.Accept);
            }
        }

        /// <summary>
        /// 获取接受回调
        /// </summary>
        /// <param name="socket"></param>
        /// <returns></returns>
        private AsyncCallback GetAcceptCallback(Socket socket)
        {
            AsyncCallback callback = null;

            callback = delegate(IAsyncResult ar)
            {
                if (this.m_ListenningSockets.Count == 0)
                    return;

                Socket receiveSocket = null;

                try
                {
                    receiveSocket = socket.EndAccept(ar);
                    receiveSocket.ReceiveTimeout = this.m_ReceiveTimeOut;
                }
                catch (SocketException se)
                {
                    this.OnErrorHappened(se, SocketOperation.Accept);
                    if (se.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        this.BeginAccept(socket, callback);
                    }
                }

                if (receiveSocket != null)
                {
                    this.ReceiveDataInternal(receiveSocket, true);
                    this.BeginAccept(socket, callback);
                }
            };

            return callback;
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="receiveSocket">接收套接字</param>
        /// <param name="async">是否异步接收:true为异步，false为同步</param>
        private void ReceiveDataInternal(Socket receiveSocket, bool async)
        {
            //获取当前接收缓冲区在整个接收缓冲区的索引
            int bufferBlockIndex = this.m_BufferManager.GetBufferBlockIndex();

            //获取当前接收缓冲区在整个接收缓冲区的偏移量
            int receiveBufferOffset = this.m_BufferManager.GetReceiveBufferOffset(bufferBlockIndex);

            string guid = Guid.NewGuid().ToString();

            if (async)
            {
                this.ReceiveAsync(receiveSocket, bufferBlockIndex, receiveBufferOffset, guid);
            }
            else
            {
                this.ReceiveSynchronize(receiveSocket, new byte[0], bufferBlockIndex, receiveBufferOffset, guid, false);
            }
        }

        /// <summary>
        /// 异步接收数据
        /// </summary>
        /// <param name="receiveSocket">接收套接字</param>
        /// <param name="bufferBlockIndex">当前接收缓冲区在整个接收缓冲区的索引</param>
        /// <param name="receiveBufferOffset">当前接收缓冲区在整个接收缓冲区的偏移量</param>
        /// <param name="guid">唯一标识此次接收</param>
        private void ReceiveAsync(Socket receiveSocket, int bufferBlockIndex, int receiveBufferOffset, string guid)
        {
            AsyncCallback receiveCallback = GetReceiveCallback(receiveSocket, bufferBlockIndex, receiveBufferOffset, guid);

            SocketError socketError;

            //开始异步接收
            receiveSocket.BeginReceive(this.m_BufferManager.ReceiveBuffer,
                                       receiveBufferOffset,
                                       this.m_BufferManager.ReceiveBufferSize,
                                       SocketFlags.None, out socketError, receiveCallback, null);

            if (socketError != SocketError.Success)
            {
                //清理接受资源
                this.ClearReceiveInfo(receiveSocket, bufferBlockIndex);
                //通知错误发生
                this.OnErrorHappened(new SocketException((int)socketError), SocketOperation.Receive);
            }
        }

        /// <summary>
        /// 获取接收回调方法
        /// </summary>
        /// <param name="receiveSocket">接收套接字</param>
        /// <param name="bufferBlockIndex">当前接收缓冲区在整个接收缓冲区的索引</param>
        /// <param name="receiveBufferOffset">当前接收缓冲区在整个接收缓冲区的偏移量</param>
        /// <param name="guid">唯一标识此次接收</param>
        /// <returns>接收回调</returns>
        private AsyncCallback GetReceiveCallback(Socket receiveSocket, int bufferBlockIndex, int receiveBufferOffset, string guid)
        {
            AsyncCallback receiveCallback = null;
            byte[] buffer = new byte[0];
            bool conditionCompleted = false;

            receiveCallback = delegate(IAsyncResult ar)
            {
                SocketError socketCallbackError;

                int receiveLength = receiveSocket.EndReceive(ar, out socketCallbackError);

                if (socketCallbackError == SocketError.Success)
                {
                    if (receiveLength > 0)
                    {
                        conditionCompleted = ProcessReceivedData(ref buffer, receiveLength,
                                            receiveBufferOffset, conditionCompleted, guid, receiveSocket.RemoteEndPoint);

                        //持续接收
                        receiveSocket.BeginReceive(this.m_BufferManager.ReceiveBuffer,
                                                   receiveBufferOffset,
                                                   this.m_BufferManager.ReceiveBufferSize,
                                                   SocketFlags.None, out socketCallbackError, receiveCallback, null);
                    }
                    else
                    {
                        this.OnReceived(buffer, guid, receiveSocket.RemoteEndPoint, true);
                        //清理接收资源
                        this.ClearReceiveInfo(receiveSocket, bufferBlockIndex);
                    }
                }
                else
                {
                    //清理接受资源
                    this.ClearReceiveInfo(receiveSocket, bufferBlockIndex);
                    //通知错误发生
                    this.OnErrorHappened(new SocketException((int)socketCallbackError), SocketOperation.Receive);
                }
            };

            return receiveCallback;
        }

        private bool ProcessReceivedData(ref byte[] buffer, int receiveLength, int receiveBufferOffset, bool conditionCompleted, string guid, EndPoint remoteEndPoint)
        {
            //当接收到的数据没有达到某一个阈值时用一个临时的buffer
            //保存接收到的数据，从而避免接收较少数据时不会频繁的触发
            //数据接收事件，也可以避免事件订阅端来为较少的数据而维护一个
            //数据结构
            buffer = this.CopyDataToBuffer(buffer, receiveLength, receiveBufferOffset);

            if (!conditionCompleted)
            {
                return buffer.Length > this.ThresholdValue;
            }

            FireDataReceivedEvent(buffer, receiveLength, receiveBufferOffset, guid, remoteEndPoint);

            //达到条件后清空buffer*******
            if (buffer.Length > 0)
                buffer = new byte[0];

            return true;
        }

        /// <summary>
        /// 将数据缓冲区数据复制到指定数据区
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="receiveLength"></param>
        /// <param name="receiveBufferOffset"></param>
        /// <returns></returns>
        private byte[] CopyDataToBuffer(byte[] buffer, int receiveLength, int receiveBufferOffset)
        {
            int index = buffer.Length;
            Array.Resize(ref buffer, buffer.Length + receiveLength);
            Array.Copy(this.m_BufferManager.ReceiveBuffer, receiveBufferOffset, buffer, index, receiveLength);
            return buffer;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="receiveLength"></param>
        /// <param name="receiveBufferOffset"></param>
        /// <param name="guid"></param>
        /// <param name="remoteEndPoint"></param>
        private void FireDataReceivedEvent(byte[] buffer, int receiveLength, int receiveBufferOffset, string guid, EndPoint remoteEndPoint)
        {
            if (buffer.Length > 0)
            {
                this.OnReceived(buffer, guid, remoteEndPoint, false);
            }
            else
            {
                //新建数据区，接收到的数据将复制到此数据区(是否可以重复利用以减少内存碎片？)
                byte[] data = new byte[receiveLength];

                //复制缓冲区数据到数据区
                Array.Copy(this.m_BufferManager.ReceiveBuffer, receiveBufferOffset, data, 0, receiveLength);

                //传递数据给接收者
                this.OnReceived(data, guid, remoteEndPoint, false);
            }
        }

        /// <summary>
        /// 清理接收数据后信息
        /// </summary>
        /// <param name="receiveSocket">接收套接字</param>
        /// <param name="bufferBlockIndex">套接字所分配的接收区间索引</param>
        private void ClearReceiveInfo(Socket receiveSocket, int bufferBlockIndex)
        {
            //释放缓冲区
            this.m_BufferManager.FreeBufferBlockIndex(bufferBlockIndex);

            receiveSocket.Shutdown(SocketShutdown.Both);
            receiveSocket.Close();
        }

        #endregion

        /// <summary>
        /// 获取TCP套接字
        /// </summary>
        /// <param name="sendTimeOut">发送超时时间</param>
        /// <param name="receiveTimeOut">接收超时时间</param>
        /// <returns>TCP套接字</returns>
        private Socket GetSocket(int sendTimeOut, int receiveTimeOut)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.SendTimeout = sendTimeOut;
            socket.ReceiveTimeout = receiveTimeOut;

            return socket;
        }

        #region 获取终结点
        private static string[] _ips;

        /// <summary>
        /// 获取本机IP列表
        /// </summary>
        /// <returns></returns>
        public static string[] GetLocalIpAddressList()
        {
            try
            {
                if (_ips == null)
                {
                    string strIp = "";
                    string[] ipList = null;
                    IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;
                    if (addressList != null && addressList.Length > 0)
                    {
                        for (int i = 0; i < addressList.Length; i++)
                        {
                            strIp += addressList[i].ToString() + ",";
                        }
                    }
                    if (!string.IsNullOrEmpty(strIp))
                    {
                        var str = strIp.Remove(strIp.Length - 1, 1);
                        ipList = str.Split(',');
                        _ips = ipList;
                    }
                }
                return _ips;
            }
            catch (Exception ex)
            {
                PlatformLogger.SystemErrorInfo("GetLocalIpAddressList:error!", ex);
                return new string[] { "127.0.0.1" };
            }
        }
        /// <summary>
        /// 获取本机IP
        /// </summary>
        /// <returns></returns>
        public static string GetLocalIpv4Address()
        {
            IPAddress ipAddress = GetIpv4Address();

            if (ipAddress != null)
                return ipAddress.ToString();

            return null;
        }

        /// <summary>
        /// 获取本机IP
        /// </summary>
        /// <returns></returns>
        public static IPAddress GetIpv4Address()
        {
            return GetIpv4Address(Environment.MachineName);
        }
        /// <summary>
        /// 获取指定主机IP
        /// </summary>
        /// <param name="hostNameOrAddress">主机名或主机IP地址</param>
        /// <returns></returns>
        public static IPAddress GetIpv4Address(string hostNameOrAddress)
        {
            try
            {
                IPAddress[] addresses = Dns.GetHostAddresses(hostNameOrAddress);

                foreach (IPAddress address in addresses)
                {
                    if (address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        return address;
                    }
                }

                return null;
            }
            catch (Exception ex)
            {
                PlatformLogger.SystemErrorInfo("GetLocalIpAddressList:error!", ex);
                return IPAddress.Parse("127.0.0.1");
            }
        }

        /// <summary>
        /// 获取本地终结点
        /// </summary>
        /// <param name="port">端口号</param>
        /// <returns>终结点</returns>
        private static EndPoint GetIpv4EndPoint(int port)
        {
            return GetIpv4EndPoint(Environment.MachineName, port);
        }

        /// <summary>
        /// 获取远程终结点
        /// </summary>
        /// <param name="hostNameOrAddress">主机名或主机IP地址</param>
        /// <param name="port">端口号</param>
        /// <returns>远程终结点</returns>
        private static EndPoint GetIpv4EndPoint(string hostNameOrAddress, int port)
        {
            IPAddress ipAddress = GetIpv4Address(hostNameOrAddress);

            if (ipAddress != null)
            {
                return new IPEndPoint(ipAddress, port);
            }

            throw new Exception("无法获取指定IP和端口的终结点");
        }

        #endregion

        /// <summary>
        /// 清理资源
        /// </summary>
        public void Dispose()
        {
            this.StopListenning(true);
        }

        #region 事件触发

        /// <summary>
        /// 触发服务监听开启事件
        /// </summary>
        private void OnServerStart(int port)
        {
            if (this.ServerStart != null)
            {
                this.ServerStart(this, new ServerPortEventArgs(port));
            }
        }

        /// <summary>
        /// 触发服务监听停止事件
        /// </summary>
        private void OnServerStop(int port)
        {
            if (this.ServerStop != null)
            {
                this.ServerStop(this, new ServerPortEventArgs(port));
            }
        }

        /// <summary>
        /// 触发开始发送事件
        /// </summary>
        private void OnSendStart()
        {
            if (this.SendStart != null)
            {
                this.SendStart(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 触发正在发送事件
        /// </summary>
        /// <param name="length">此次发送的长度</param>
        private void OnSending(int length)
        {
            if (this.Sending != null)
            {
                this.Sending(this, new DataSendEventArgs(length));
            }
        }

        /// <summary>
        /// 触发发送完成事件
        /// </summary>
        private void OnSendCompleted()
        {
            if (this.SendCompleted != null)
            {
                this.SendCompleted(this, EventArgs.Empty);
            }
        }

        private void OnReceived(byte[] data, string guid, EndPoint remoteEndPoint, bool isCompleted)
        {
            if (this.DataReceived != null)
            {
                this.DataReceived(this, new DataReceivedEventArgs(data, remoteEndPoint, guid, isCompleted));
            }
        }

        /// <summary>
        /// 触发发生socket错误事件
        /// </summary>
        /// <param name="socketException"></param>
        private void OnErrorHappened(SocketException socketException, SocketOperation errorOperation)
        {
            if (this.ErrorHappened != null)
            {
                this.ErrorHappened(this, new SocketErrorEventArgs(socketException, errorOperation));
            }
        }

        #endregion
    }

    public enum SocketOperation
    {
        // 摘要:
        //     没有套接字操作。
        None = 0,
        //
        // 摘要:
        //     一个套接字 Accept 操作。
        Accept = 1,
        //
        // 摘要:
        //     一个套接字 Connect 操作。
        Connect = 2,
        //
        // 摘要:
        //     一个套接字 Disconnect 操作。
        Disconnect = 3,
        //
        // 摘要:
        //     一个套接字 Receive 操作。
        Receive = 4,
        //
        // 摘要:
        //     一个套接字 ReceiveFrom 操作。
        ReceiveFrom = 5,
        //
        // 摘要:
        //     一个套接字 ReceiveMessageFrom 操作。
        ReceiveMessageFrom = 6,
        //
        // 摘要:
        //     一个套接字 Send 操作。
        Send = 7,
        //
        // 摘要:
        //     一个套接字 SendPackets 操作。
        SendPackets = 8,
        //
        // 摘要:
        //     一个套接字 SendTo 操作。
        SendTo = 9,

        Bind
    }

    public class ServerPortEventArgs : EventArgs
    {
        private int m_Port;

        public int Port
        {
            get { return m_Port; }
        }

        public ServerPortEventArgs(int port)
        {
            this.m_Port = port;
        }
    }

    public class DataReceivedEventArgs : EventArgs
    {
        private byte[] m_Data;
        /// <summary>
        /// 接收到的数据
        /// </summary>
        public byte[] Data
        {
            get { return this.m_Data; }
        }

        private EndPoint m_RemoteEndPoint;
        /// <summary>
        /// 远程终结点
        /// </summary>
        public EndPoint RemoteEndPoint
        {
            get { return m_RemoteEndPoint; }
        }

        private string m_Guid;
        /// <summary>
        /// 唯一标识一次接收
        /// </summary>
        public string Guid
        {
            get { return m_Guid; }
        }

        private bool m_IsCompleted;

        /// <summary>
        /// 接收是否完成
        /// </summary>
        public bool IsCompleted
        {
            get { return m_IsCompleted; }
        }

        public DataReceivedEventArgs(byte[] data, EndPoint remotePoint, string guid, bool isCompleted)
        {
            this.m_Data = data;
            this.m_RemoteEndPoint = remotePoint;
            this.m_Guid = guid;
            this.m_IsCompleted = isCompleted;
        }
    }

    public class SocketErrorEventArgs : EventArgs
    {
        private SocketException m_SocketException;

        public SocketException SocketException
        {
            get { return this.m_SocketException; }
        }

        private SocketOperation m_ErrorOperation;

        public SocketOperation ErrorOperation
        {
            get { return m_ErrorOperation; }
        }

        public SocketErrorEventArgs(SocketException socketException, SocketOperation errorOperation)
        {
            this.m_SocketException = socketException;
            this.m_ErrorOperation = errorOperation;
        }
    }

    public class DataSendEventArgs : EventArgs
    {
        private int m_Length;

        public int Length
        {
            get { return m_Length; }
        }

        public DataSendEventArgs(int length)
        {
            this.m_Length = length;
        }
    }
}