Пример #1
0
        /// <summary>
        /// Pop the current server and put onto the end of the list.
        /// Select head of list as long as number of reconnect attempts under MaxReconnect.
        /// </summary>
        /// <returns>The next server endpoint, or null</returns>
        internal ServerConnectionStatus SelectNextServer()
        {
            lock (this._locker)
            {
                ServerConnectionStatus s = this._currentServer;
                if (s == null)
                {
                    return(null);
                }

                //remove the current server.
                this._servers.Remove(s);

                if (this._options.MaxReconnect > 0 &&
                    s.ReconnectionCount < this._options.MaxReconnect
                    )
                {
                    //if we haven't surpassed max reconnects, add it to try again.
                    this._servers.AddLast(s);
                }

                this._currentServer = this._servers.FirstOrDefault();
                return(this._currentServer);
            }
        }
Пример #2
0
        /// <summary>
        /// Creates an instance of <see cref="TcpConnection"/> using the
        /// specified <see cref="ServerConnectionStatus"/> as parameters.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="s"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        internal static TcpConnection Create(
            ClientOptions options,
            ServerConnectionStatus s,
            CancellationToken token
            )
        {
            var instance = new TcpConnection();

            instance._options = options;

            var client = new TcpClient();

            try
            {
                //it seems there's no way to better make a connection attempt
                //within a certain timeout.
                //the solution is connecting in the async-fashion, then
                //controlling the task timeout and cancellation in the sync-fashion
                bool success = client
                               .ConnectAsync(s.EndPoint.Address, s.EndPoint.Port)
                               .Wait((int)options.Timeout.TotalMilliseconds, token);

                if (success)
                {
                    //set-up the socket
                    client.NoDelay           = false;
                    client.ReceiveBufferSize = Defaults.defaultBufSize * 2;
                    client.SendBufferSize    = Defaults.defaultBufSize;
                    client.SendTimeout       = InitialSocketSendTimeout;
                    client.ReceiveTimeout    = InitialSocketReceiveTimeout;
                    instance._client         = client;
                    instance._netStream      = client.GetStream();

                    // save off the hostname
                    instance._hostName = s.EndPoint.Address.ToString();

                    instance.CreateReaderWriter();
                }
                else
                {
                    throw new NATSConnectionException("timeout");
                }
            }
            catch (Exception ex)
            {
                client.Dispose();
                throw ex;
            }
            //Console.WriteLine("socket connected");
            return(instance);
        }
Пример #3
0
        /// <summary>
        /// Main entry-point to connect to a server
        /// </summary>
        /// <param name="initialPresentation">Indicates whether it's the very first attempt to connect,
        /// or rather some retry due to a connection drop.</param>
        /// <param name="token">Propagates notification that operations should be canceled.</param>
        /// <returns>The <see cref="TcpConnection"/> useful to exchange data with the server.</returns>
        internal TcpConnection ConnectToAServer(
            bool initialPresentation,
            CancellationToken token
            )
        {
            //select an iterator against the proper server list
            IEnumerator <ServerConnectionStatus> iter;

            lock (this._locker)
            {
                if (initialPresentation)
                {
                    iter = this._servers.GetEnumerator();
                }
                else
                {
                    iter = new ServerStatusEnumerator(this);
                }
            }

            //task cancelation will raise an exception
            token.ThrowIfCancellationRequested();

            Exception lastex = null;

            while (iter.MoveNext())
            {
                ServerConnectionStatus s = iter.Current;
                try
                {
                    //connection attempt
                    var tcp = TcpConnection.Create(this._options, s, token);
                    s.DidConnect        = true;
                    s.ReconnectionCount = 0;
                    this._currentServer = s;
                    return(tcp);
                }
                catch (OperationCanceledException ex)
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    lastex = ex;
                }

                if (initialPresentation == false)
                {
                    //manage stats
                    s.ReconnectionCount++;
                    this.IncrementStatsCounter?.Invoke();

                    //waits before retrying again
                    Helpers.CancelableDelay(this._options.ReconnectWait, token);
                }
            }

            if (lastex != null)
            {
                throw lastex;
            }

            this._currentServer = null;
            return(null);
        }