basesocketconnectionhost.cs

来自「ActiveSync数据同步」· CS 代码 · 共 1,663 行 · 第 1/4 页

CS
1,663
字号
/* ====================================================================
 * Copyright (c) 2007 Andre Luis Azevedo (az.andrel@yahoo.com.br)
 * All rights reserved.
 *                       
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    In addition, the source code must keep original namespace names.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution. In addition, the binary form must keep the original 
 *    namespace names and original file name.
 * 
 * 3. The name "ALAZ" or "ALAZ Library" must not be used to endorse or promote 
 *    products derived from this software without prior written permission.
 *
 * 4. Products derived from this software may not be called "ALAZ" or
 *    "ALAZ Library" nor may "ALAZ" or "ALAZ Library" appear in their 
 *    names without prior written permission of the author.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

using System;
using System.Collections.Generic;

using System.Threading;
using System.Xml.Serialization;
using System.Security.Cryptography;

using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.IO;
using System.Text;

using ALAZ.SystemEx.ThreadingEx;

namespace ALAZ.SystemEx.NetEx.SocketsEx
{

    /// <summary>
    /// The connection host.
    /// </summary>
    public abstract class BaseSocketConnectionHost : BaseDisposable
    {

        #region Fields

        private bool FActive;
        private object FSyncActive;

        private HostType FHostType;
        private long FConnectionId;

        //----- Enumerates the connections and creators!
        private ReaderWriterLock FSocketConnectionsSync;
        private Dictionary<long, BaseSocketConnection> FSocketConnections;

        private List<BaseSocketConnectionCreator> FSocketCreators;

        //----- The Socket Service.
        private ISocketService FSocketService;

        //----- Waits for objects removing!
        private ManualResetEvent FWaitCreatorsDisposing;
        private ManualResetEvent FWaitConnectionsDisposing;
        private ManualResetEvent FWaitThreadsDisposing;

        //----- Check idle timer!
        private Timer FIdleTimer;
        private int FIdleCheckInterval;
        private int FIdleTimeOutValue;

        //----- Socket delimiter and buffer size!
        private byte[] FDelimiter;
        private DelimiterType FDelimiterType;

        private int FMessageBufferSize;
        private int FSocketBufferSize;
        
        #endregion

        #region Constructor

        /// <summary>
        /// Base creator for BaseSocketConnectionHost.
        /// </summary>
        /// <param name="hostType">
        /// Host type.
        /// </param>
        /// <param name="socketService">
        /// Socket service.
        /// </param>
        /// <param name="delimiterType">
        /// Delimiter type.
        /// </param>
        /// <param name="delimiter">
        /// Delimiter byte array.
        /// </param>
        /// <param name="socketBufferSize">
        /// Socket buffer size.
        /// </param>
        /// <param name="messageBufferSize">
        /// Max message buffer size.
        /// </param>
        /// <param name="idleCheckInterval">
        /// Idle check interval timeout.
        /// </param>
        /// <param name="idleTimeOutValue">
        /// Idle connection timeout.
        /// </param>
        public BaseSocketConnectionHost(HostType hostType, ISocketService socketService, DelimiterType delimiterType, byte[] delimiter, int socketBufferSize, int messageBufferSize, int idleCheckInterval, int idleTimeOutValue)
        {

            FHostType = hostType;
            FConnectionId = 1000;

            FSocketConnectionsSync = new ReaderWriterLock();

            FSocketConnections = new Dictionary<long, BaseSocketConnection>();
            FSocketCreators = new List<BaseSocketConnectionCreator>();
            FSocketService = socketService;

            FWaitCreatorsDisposing = new ManualResetEvent(false);
            FWaitConnectionsDisposing = new ManualResetEvent(false);
            FWaitThreadsDisposing = new ManualResetEvent(false);

            FIdleCheckInterval = idleCheckInterval;
            FIdleTimeOutValue = idleTimeOutValue;

            if ( (FIdleCheckInterval > 0) && (FIdleTimeOutValue > 0) )
            {
                FIdleTimer = new Timer(new TimerCallback(CheckSocketConnections));
            }

            FDelimiter = delimiter;
            FDelimiterType = delimiterType;

            FMessageBufferSize = messageBufferSize;
            FSocketBufferSize = socketBufferSize;

            FActive = false;
            FSyncActive = new Object();

        }

        #endregion

        #region Destructor

        protected override void Free(bool canAccessFinalizable)
        {

            if (FIdleTimer != null)
            {
                FIdleTimer.Dispose();
                FIdleTimer = null;
            }

            if (FWaitCreatorsDisposing != null)
            {
                FWaitCreatorsDisposing.Set();
                FWaitCreatorsDisposing.Close();
                FWaitCreatorsDisposing = null;
            }

            if (FWaitConnectionsDisposing != null)
            {
                FWaitConnectionsDisposing.Set();
                FWaitConnectionsDisposing.Close();
                FWaitConnectionsDisposing = null;
            }

            if (FWaitThreadsDisposing != null)
            {
                FWaitThreadsDisposing.Set();
                FWaitThreadsDisposing.Close();
                FWaitThreadsDisposing = null;
            }

            if (FSocketConnections != null)
            {
                FSocketConnections.Clear();
                FSocketConnections = null;
            }

            if (FSocketCreators != null)
            {
                FSocketCreators.Clear();
                FSocketCreators = null;
            }

            FSocketConnectionsSync = null;
            FSocketService = null;
            FDelimiter = null;

            base.Free(canAccessFinalizable);

        }

        #endregion

        #region Methods

        #region Start

        /// <summary>
        /// Starts the base host.
        /// </summary>
        public void Start()
        {

            if (!Disposed)
            {

                int loopSleep = 0;
                
                foreach (BaseSocketConnectionCreator creator in FSocketCreators)
                {
                    creator.Start();
                    ThreadEx.LoopSleep(ref loopSleep);
                }

                if (FIdleTimer != null)
                {
                    FIdleTimer.Change(FIdleTimeOutValue, FIdleTimeOutValue);
                }

                Active = true;

            }

        }

        #endregion

        #region Stop

        /// <summary>
        /// Stop the base host.
        /// </summary>
        public virtual void Stop()
        {
            Active = false;
            Dispose();
        }

        #endregion

        #region StopCreators

        /// <summary>
        /// Stop the host creators.
        /// </summary>
        protected void StopCreators()
        {

            //----- Stop Creators!
            BaseSocketConnectionCreator[] creators = GetSocketCreators();

            if (creators != null)
            {

                FWaitCreatorsDisposing.Reset();

                int loopCount = 0;
                
                foreach (BaseSocketConnectionCreator creator in creators)
                {
                
                    try
                    {
                        
                        creator.Stop();
                        
                    }
                    finally
                    {

                        RemoveCreator(creator);
                        creator.Dispose();

                        ThreadEx.LoopSleep(ref loopCount);

                    }

                }

                if (creators.Length > 0)
                {
                    FWaitCreatorsDisposing.WaitOne(10000, false);
                }

            }

        }

        #endregion

        #region StopConnections

        protected void StopConnections()
        {

            if (!Disposed)
            {

                //----- Stop Connections!
                BaseSocketConnection[] connections = GetSocketConnections();

                if (connections != null)
                {

                    FWaitConnectionsDisposing.Reset();
                    
                    int loopSleep = 0;

                    foreach (BaseSocketConnection connection in connections)
                    {
                        connection.BeginDisconnect();
                        ThreadEx.LoopSleep(ref loopSleep);
                    }

                    if (connections.Length > 0)
                    {
                        FWaitConnectionsDisposing.WaitOne(10000, false);
                    }

                }


            }

        }

        #endregion

        #region Fire Methods

        #region FireOnConnected

        internal void FireOnConnected(BaseSocketConnection connection)
        {

            if (connection.Active)
            {
                FSocketService.OnConnected(new ConnectionEventArgs(connection));
            }

        }

        #endregion

        #region FireOnSent

        private void FireOnSent(BaseSocketConnection connection, byte[] buffer, bool sentByServer)
        {
            
            if (connection.Active)
            {
                FSocketService.OnSent(new MessageEventArgs(connection, buffer, sentByServer));
            }

        }

        #endregion

        #region FireOnReceived

        private void FireOnReceived(BaseSocketConnection connection, byte[] buffer, bool readCanEnqueue)
        {

            if (connection.Active)
            {

                if (!readCanEnqueue)
                {

                    lock (connection.SyncReadCount)
                    {
                        connection.ReadCanEnqueue = false;
                    }

                }

                FSocketService.OnReceived(new MessageEventArgs(connection, buffer, false));

                if (!readCanEnqueue)
                {

                    lock (connection.SyncReadCount)
                    {
                        connection.ReadCanEnqueue = true;
                    }

                }

            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?