public static bool TryConnect(this Socket socket, EndPoint remoteEndpoint, int millisecondsTimeout)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                using (var mre = new ManualResetEventSlim(false))
                {
                    using (var sea = new SocketAsyncEventArgs()
                    {
                        RemoteEndPoint = remoteEndpoint, UserToken = mre
                    })
                    {
                        sea.Completed += (s, e) => ((ManualResetEventSlim)e.UserToken).Set();

                        var pending = socket.ConnectAsync(sea);

                        if (!pending || mre.Wait(millisecondsTimeout))
                        {
                            return(sea.SocketError == SocketError.Success);
                        }

                        Socket.CancelConnectAsync(sea); // this will close the socket!

                        // In case of time-out, ManualResetEventSlim is left undisposed to avoid race conditions,
                        // letting SafeHandle's finalizer to do the cleanup.
                        return(false);
                    }
                }
            }
            else
            {
                throw new PlatformNotSupportedException();
            }
        }
示例#2
0
        /// <summary>
        /// Disconnect the client (synchronous)
        /// </summary>
        /// <returns>'true' if the client was successfully disconnected, 'false' if the client is already disconnected</returns>
        public virtual bool Disconnect()
        {
            if (!IsConnected && !IsConnecting)
            {
                return(false);
            }

            // Cancel connecting operation
            if (IsConnecting)
            {
                Socket.CancelConnectAsync(_connectEventArg);
            }

            // Reset event args
            _connectEventArg.Completed -= OnAsyncCompleted;
            _receiveEventArg.Completed -= OnAsyncCompleted;
            _sendEventArg.Completed    -= OnAsyncCompleted;

            // Call the client disconnecting handler
            OnDisconnecting();

            Socket.SafeClose();

            // Update the connected flag
            IsConnected = false;

            // Call the client disconnected handler
            OnDisconnected();

            return(true);
        }
示例#3
0
        public void CancelConnectAsync_StaticConnect_CancelsInProgressConnect()
        {
            using (var listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                listen.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                using (var connectSaea = new SocketAsyncEventArgs())
                {
                    var tcs = new TaskCompletionSource <SocketError>();
                    connectSaea.Completed     += (s, e) => tcs.SetResult(e.SocketError);
                    connectSaea.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listen.LocalEndPoint).Port);

                    bool pending = Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, connectSaea);
                    if (!pending)
                    {
                        tcs.SetResult(connectSaea.SocketError);
                    }
                    if (tcs.Task.IsCompleted)
                    {
                        Assert.NotEqual(SocketError.Success, tcs.Task.Result);
                    }

                    Socket.CancelConnectAsync(connectSaea);
                }
            }
        }
        // Tries to connect within the provided timeout interval
        // Useful to speed up "can not connect" assertions on Windows
        public static bool TryConnect(this Socket socket, EndPoint remoteEndpoint, int millisecondsTimeout)
        {
            var mre = new ManualResetEventSlim(false);

            using var sea = new SocketAsyncEventArgs()
                  {
                      RemoteEndPoint = remoteEndpoint,
                      UserToken      = mre
                  };

            sea.Completed += (s, e) => ((ManualResetEventSlim)e.UserToken).Set();

            bool pending = socket.ConnectAsync(sea);

            if (!pending || mre.Wait(millisecondsTimeout))
            {
                mre.Dispose();
                return(sea.SocketError == SocketError.Success);
            }

            Socket.CancelConnectAsync(sea); // this will close the socket!

            // In case of time-out, ManualResetEventSlim is left undisposed to avoid race conditions,
            // letting SafeHandle's finalizer to do the cleanup.
            return(false);
        }
示例#5
0
        public static async ValueTask <(Socket, Stream)> ConnectAsync(string host, int port, CancellationToken cancellationToken)
        {
            // Rather than creating a new Socket and calling ConnectAsync on it, we use the static
            // Socket.ConnectAsync with a SocketAsyncEventArgs, as we can then use Socket.CancelConnectAsync
            // to cancel it if needed. Rent or allocate one.
            ConnectEventArgs saea;

            if (!s_connectEventArgs.TryDequeue(out saea))
            {
                saea = new ConnectEventArgs();
            }

            try
            {
                saea.Initialize(cancellationToken);

                // Configure which server to which to connect.
                saea.RemoteEndPoint = IPAddress.TryParse(host, out IPAddress address) ?
                                      (EndPoint) new IPEndPoint(address, port) :
                                      new DnsEndPoint(host, port);

                // Initiate the connection.
                if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, saea))
                {
                    // Connect completing asynchronously. Enable it to be canceled and wait for it.
                    using (cancellationToken.Register(s => Socket.CancelConnectAsync((SocketAsyncEventArgs)s), saea))
                    {
                        await saea.Builder.Task.ConfigureAwait(false);
                    }
                }
                else if (saea.SocketError != SocketError.Success)
                {
                    // Connect completed synchronously but unsuccessfully.
                    throw new SocketException((int)saea.SocketError);
                }

                Debug.Assert(saea.SocketError == SocketError.Success, $"Expected Success, got {saea.SocketError}.");
                Debug.Assert(saea.ConnectSocket != null, "Expected non-null socket");

                // Configure the socket and return a stream for it.
                Socket socket = saea.ConnectSocket;
                socket.NoDelay = true;
                return(socket, new NetworkStream(socket, ownsSocket: true));
            }
            catch (Exception error)
            {
                throw CancellationHelper.ShouldWrapInOperationCanceledException(error, cancellationToken) ?
                      CancellationHelper.CreateOperationCanceledException(error, cancellationToken) :
                      new HttpRequestException(error.Message, error);
            }
            finally
            {
                // Pool the event args, or if the pool is full, dispose of it.
                saea.Clear();
                if (!s_connectEventArgs.TryEnqueue(saea))
                {
                    saea.Dispose();
                }
            }
        }
示例#6
0
        /// <summary>
        /// Disconnect the client (synchronous)
        /// </summary>
        /// <returns>'true' if the client was successfully disconnected, 'false' if the client is already disconnected</returns>
        public virtual bool Disconnect()
        {
            if (!IsConnected && !IsConnecting)
            {
                return(false);
            }

            // Cancel connecting operation
            if (IsConnecting)
            {
                Socket.CancelConnectAsync(_connectEventArg);
            }

            // Reset event args
            _connectEventArg.Completed -= OnAsyncCompleted;
            _receiveEventArg.Completed -= OnAsyncCompleted;
            _sendEventArg.Completed    -= OnAsyncCompleted;

            try
            {
                try
                {
                    // Shutdown the socket associated with the client
                    Socket.Shutdown(SocketShutdown.Both);
                }
                catch (SocketException) {}

                // Close the client socket
                Socket.Close();

                // Dispose the client socket
                Socket.Dispose();

                // Dispose event arguments
                _connectEventArg.Dispose();
                _receiveEventArg.Dispose();
                _sendEventArg.Dispose();

                // Update the client socket disposed flag
                IsSocketDisposed = true;
            }
            catch (ObjectDisposedException) {}

            // Update the connected flag
            IsConnected = false;

            // Update sending/receiving flags
            _receiving = false;
            _sending   = false;

            // Clear send/receive buffers
            ClearBuffers();

            // Call the client disconnected handler
            OnDisconnected();

            return(true);
        }
            /// <summary>
            /// Timeout current probe
            /// </summary>
            /// <param name="state"></param>
            private void OnTimerTimeout(object state)
            {
                if (!_lock.Wait(0))
                {
                    // lock is taken either by having completed or having re-begun.
                    return;
                }
                try {
                    switch (_state)
                    {
                    case State.Timeout:
                        return;

                    case State.Connect:
                        //
                        // Cancel current arg and mark as timedout which will
                        // dispose the arg and open a new one.  Should the arg
                        // still complete later it will be in terminal state.
                        //
                        Socket.CancelConnectAsync(_arg);
                        _state           = State.Timeout;
                        _arg.SocketError = SocketError.TimedOut;
                        return;

                    case State.Probe:
                        _outer._logger.Debug("Probe {index} {remoteEp} timed out...",
                                             _outer._index, _arg.RemoteEndPoint);
                        _arg.SocketError = SocketError.TimedOut;
                        _state           = State.Timeout;
                        if (_outer._probe.Reset())
                        {
                            // We will get a disconnect complete callback now.
                            return;
                        }
                        //
                        // There was nothing to cancel so start from beginning.
                        // Since connect socket is connected, go to begin state
                        // This will close the socket and reconnect a new one.
                        //
                        _outer._logger.Information(
                            "Probe {index} not cancelled - try restart...",
                            _outer._index);
                        _state = State.Begin;
                        _outer.OnBegin();
                        return;
                    }
                }
                catch (Exception ex) {
                    _outer._logger.Debug(ex,
                                         "Error during timeout of probe {index}", _outer._index);
                }
                finally {
                    _lock.Release();
                }
            }
示例#8
0
文件: SocketTest.cs 项目: ynkbt/moon
        public void CancelConnectAsync()
        {
            Assert.Throws <ArgumentNullException> (delegate {
                Socket.CancelConnectAsync(null);
            }, "null");

            SocketAsyncEventArgs saea = new SocketAsyncEventArgs();

            Assert.IsNull(saea.RemoteEndPoint, "RemoteEndPoint");
            Socket.CancelConnectAsync(saea);
            // no exception
        }
 private void CannelConnecting()
 {
     try
     {
         Socket.CancelConnectAsync(receiveAsyncEventArgs);
     }
     catch (Exception ex)
     {
         if (errorRecorder != null)
         {
             errorRecorder.RecordError("Cannel connecting exception. Remote endpoint: " + endpoint + ".", ex);
         }
     }
 }
        private async ValueTask <Stream> ConnectAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            //TODO: this object need pooling
            var saea = new SocketAsyncEventArgs();

            var taskBuilder = new AsyncTaskMethodBuilder();

            _ = taskBuilder.Task;

            saea.Completed += (s, args) =>
            {
                switch (args.SocketError)
                {
                case SocketError.Success:
                    taskBuilder.SetResult();
                    break;

                case SocketError.OperationAborted:
                case SocketError.ConnectionAborted:
                    if (cancellationToken.CanBeCanceled)
                    {
                        taskBuilder.SetException(new OperationCanceledException("JOJO 我不做人啦!"));
                        break;
                    }
                    goto default;

                default:
                    taskBuilder.SetException(new SocketException((int)args.SocketError));
                    break;
                }
            };

            saea.RemoteEndPoint = _poolManager.settings.EndPointProvider.GetEndPoint(_host, _port);

            if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, saea))
            {
                using (cancellationToken.Register((s) => Socket.CancelConnectAsync((SocketAsyncEventArgs)s), saea))
                {
                    //waiting for Completed event emit
                    await taskBuilder.Task.ConfigureAwait(false);
                }
            }

            Socket socket = saea.ConnectSocket;
            var    stream = new NetworkStream(socket);

            socket.NoDelay = true;

            return(new ExposedSocketNetworkStream(socket, ownsSocket: true));
        }
示例#11
0
 public async static ValueTask ConnectAsync(this Socket socket, EndPoint remoteEP, CancellationToken cancellationToken = default)
 {
     await FromAsyncEventArgs(
         socket,
         (s, e, a) =>
     {
         e.RemoteEndPoint = a.RemoteEP;
         return(s.ConnectAsync(e));
     },
         (s) => Unit.Default,
         (e) => Socket.CancelConnectAsync(e),
         new { RemoteEP = remoteEP },
         cancellationToken);
 }
示例#12
0
 private void ConnectCancelled(ConnectToken token, SocketAsyncEventArgs e)
 {
     if (token.IsCompleted)
     {
         return;
     }
     Socket.CancelConnectAsync(e);
     if (token.IsCompleted)
     {
         return;
     }
     ((ConnectToken)e.UserToken).TrySetCanceled();
     ClearConnect(e);
 }
示例#13
0
        public static async ValueTask <Stream> ConnectAsync(string host, int port, CancellationToken cancellationToken)
        {
            // Rather than creating a new Socket and calling ConnectAsync on it, we use the static
            // Socket.ConnectAsync with a SocketAsyncEventArgs, as we can then use Socket.CancelConnectAsync
            // to cancel it if needed.
            var saea = new ConnectEventArgs();

            try
            {
                saea.Initialize(cancellationToken);

                // Configure which server to which to connect.
                saea.RemoteEndPoint = new DnsEndPoint(host, port);

                // Initiate the connection.
                if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, saea))
                {
                    // Connect completing asynchronously. Enable it to be canceled and wait for it.
                    using (cancellationToken.UnsafeRegister(s => Socket.CancelConnectAsync((SocketAsyncEventArgs)s), saea))
                    {
                        await saea.Builder.Task.ConfigureAwait(false);
                    }
                }
                else if (saea.SocketError != SocketError.Success)
                {
                    // Connect completed synchronously but unsuccessfully.
                    throw new SocketException((int)saea.SocketError);
                }

                Debug.Assert(saea.SocketError == SocketError.Success, $"Expected Success, got {saea.SocketError}.");
                Debug.Assert(saea.ConnectSocket != null, "Expected non-null socket");

                // Configure the socket and return a stream for it.
                Socket socket = saea.ConnectSocket;
                socket.NoDelay = true;
                return(new ExposedSocketNetworkStream(socket, ownsSocket: true));
            }
            catch (Exception error) when(!(error is OperationCanceledException))
            {
                throw CancellationHelper.ShouldWrapInOperationCanceledException(error, cancellationToken) ?
                      CancellationHelper.CreateOperationCanceledException(error, cancellationToken) :
                      new HttpRequestException(error.Message, error, RequestRetryType.RetryOnNextProxy);
            }
            finally
            {
                saea.Dispose();
            }
        }
示例#14
0
        public void CancelConnectAsync_StaticConnect_CancelsInProgressConnect()
        {
            using (var listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                listen.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                using (var connectSaea = new SocketAsyncEventArgs())
                {
                    var tcs = new TaskCompletionSource <bool>();
                    connectSaea.Completed     += delegate { tcs.SetResult(true); };
                    connectSaea.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listen.LocalEndPoint).Port);

                    Assert.True(Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, connectSaea));
                    Assert.False(tcs.Task.IsCompleted);

                    Socket.CancelConnectAsync(connectSaea);
                }
            }
        }
示例#15
0
 /// <summary>
 /// Dispose probe
 /// </summary>
 public void Dispose()
 {
     _lock.Wait();
     try {
         if (_state != State.Disposed)
         {
             Socket.CancelConnectAsync(_arg);
             _arg.ConnectSocket.SafeDispose();
             _socket.SafeDispose();
             _arg.Dispose();
             _timer.Dispose();
             _state = State.Disposed;
         }
     }
     finally {
         _lock.Release();
     }
 }
示例#16
0
        /// <summary>
        ///		Establishes logical connection, which specified to the managed transport protocol, for the server.
        /// </summary>
        /// <param name="targetEndPoint">The end point of target server.</param>
        /// <returns>
        ///		<see cref="Task{T}"/> of <see cref="ClientTransport"/> which represents asynchronous establishment process specific to the managed transport.
        ///		This value will not be <c>null</c>.
        /// </returns>
        protected sealed override Task <ClientTransport> ConnectAsyncCore(EndPoint targetEndPoint)
        {
            var source  = new TaskCompletionSource <ClientTransport>();
            var context = new SocketAsyncEventArgs {
                RemoteEndPoint = targetEndPoint
            };

            context.Completed += OnCompleted;

            MsgPackRpcClientProtocolsTrace.TraceEvent(
                MsgPackRpcClientProtocolsTrace.BeginConnect,
                "Connecting. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3} }}",
                targetEndPoint,
                targetEndPoint.AddressFamily,
                Configuration.PreferIPv4,
                Socket.OSSupportsIPv6
                );

            context.UserToken =
                Tuple.Create(
                    source,
                    BeginConnectTimeoutWatch(
                        () => {
                MsgPackRpcClientProtocolsTrace.TraceEvent(
                    MsgPackRpcClientProtocolsTrace.ConnectTimeout,
                    "Connect timeout. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3}, \"ConnectTimeout\" : {4} }}",
                    targetEndPoint,
                    targetEndPoint.AddressFamily,
                    Configuration.PreferIPv4,
                    Socket.OSSupportsIPv6,
                    Configuration.ConnectTimeout
                    );
                Socket.CancelConnectAsync(context);
            }
                        )
                    );

            if (!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, context))
            {
                OnCompleted(null, context);
            }

            return(source.Task);
        }
示例#17
0
        private void PerformConnect(IPEndPoint endpoint, CancellationToken token)
        {
            this.endpoint = endpoint;
            this.name     = endpoint.ToString();
            this.IsAlive  = false;

            var sw = Stopwatch.StartNew();

            InitBuffers();

            using (var mre = new ManualResetEventSlim(false))
                using (var opt = new SocketAsyncEventArgs {
                    RemoteEndPoint = endpoint
                })
                {
                    CoreEventSource.ConnectStart(name);

                    opt.Completed += (a, b) => mre.Set();
                    RecreateSocket();

                    try
                    {
                        if (socket.ConnectAsync(opt) &&
                            !mre.Wait((int)ConnectionTimeout.TotalMilliseconds, token))
                        {
                            CoreEventSource.ConnectFail(name, SocketError.TimedOut);
                            Socket.CancelConnectAsync(opt);
                            throw new TimeoutException($"Connection timeout {ConnectionTimeout} has been exceeded while trying to connect to {endpoint}");
                        }

                        if (opt.SocketError != SocketError.Success)
                        {
                            CoreEventSource.ConnectFail(name, opt.SocketError);
                            throw new IOException($"Could not connect to {endpoint}");
                        }

                        IsAlive = true;
                    }
                    finally
                    {
                        LogTo.Info($"Connected to {endpoint} in {sw.ElapsedMilliseconds} msec");
                    }
                }
        }
 public void CancelConnect()
 {
     try
     {
         if (m_isConnecting && m_socketConnectionArgs != null)
         {
             Socket.CancelConnectAsync(m_socketConnectionArgs);
             m_socket.Close();
         }
         //else
         //{
         //    logger.Warn("SilverlightTCPSIPChannel CancelConnect was called on a socket that's not in the connecting state.");
         //}
     }
     catch (Exception excp)
     {
         logger.Error("Exception SilverlightTCPSIPChannel CancelConnect. " + excp.Message);
     }
 }
        public void CancelConnectAsync_InstanceConnect_CancelsInProgressConnect()
        {
            using (var listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    listen.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                    using (var connectSaea = new SocketAsyncEventArgs())
                    {
                        var tcs = new TaskCompletionSource <SocketError>();
                        connectSaea.Completed     += (s, e) => tcs.SetResult(e.SocketError);
                        connectSaea.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listen.LocalEndPoint).Port);

                        Assert.True(client.ConnectAsync(connectSaea), $"ConnectAsync completed synchronously with SocketError == {connectSaea.SocketError}");
                        if (tcs.Task.IsCompleted)
                        {
                            Assert.NotEqual(SocketError.Success, tcs.Task.Result);
                        }

                        Socket.CancelConnectAsync(connectSaea);
                        Assert.False(client.Connected, "Expected Connected to be false");
                    }
                }
        }
示例#20
0
        public async ValueTask <ConnectionContext> ConnectAsync(EndPoint endpoint, CancellationToken cancellationToken)
        {
            var socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
            {
                LingerState = new LingerOption(true, 0),
                NoDelay     = true
            };

            socket.EnableFastPath();
            using var completion = new SingleUseSocketAsyncEventArgs
                  {
                      RemoteEndPoint = endpoint
                  };

            if (socket.ConnectAsync(completion))
            {
                using (cancellationToken.Register(s => Socket.CancelConnectAsync((SingleUseSocketAsyncEventArgs)s), completion))
                {
                    await completion.Task;
                }
            }

            if (completion.SocketError != SocketError.Success)
            {
                if (completion.SocketError == SocketError.OperationAborted)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }
                throw new SocketConnectionException($"Unable to connect to {endpoint}. Error: {completion.SocketError}");
            }

            var scheduler  = this.schedulers.GetScheduler();
            var connection = new SocketConnection(socket, this.memoryPool, scheduler, this.trace);

            connection.Start();
            return(connection);
        }
示例#21
0
        private async Task CreateSocketAsync(DnsEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout)
        {
            CancellationTokenSource cancellationConnTimeout = null;

            if (connectionTimeout != TimeSpan.MaxValue)
            {
                cancellationConnTimeout = new CancellationTokenSource(connectionTimeout);
            }

            var args = new ConnectEventArgs();

            args.RemoteEndPoint = endpoint;

            if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, args))
            {
                if (cancellationConnTimeout != null)
                {
                    using (cancellationConnTimeout.Token.Register(s => Socket.CancelConnectAsync((SocketAsyncEventArgs)s), args))
                    {
                        await args.Builder.Task.ConfigureAwait(false);
                    }
                }
            }
            else if (args.SocketError != SocketError.Success)
            {
                throw new SocketException((int)args.SocketError);
            }

            _socket = args.ConnectSocket;
            _socket.ReceiveTimeout = receiveTimeout == TimeSpan.MaxValue
                ? Timeout.Infinite
                : (int)receiveTimeout.TotalMilliseconds;
            _socket.NoDelay = true;
            _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

            _inputStream = new NetworkStream(_socket, ownsSocket: true);
        }
        /// <summary>
        /// Establishes whether or not connectivity can be made to the given <see cref="DnsEndPoint"/>.
        /// Throws a more helpful exception if the connection attempt fails. This can be used to alleviate
        /// the dreaded "No such host is known." error message when a DNS lookup fails, by returning a message
        /// stating what hostname was attempted.
        /// </summary>
        /// <param name="endPoint">The endpoint to attempt a dummy socket connection.</param>
        /// <param name="name">The name to use in the error message, in case connection failed.</param>
        /// <param name="timeout">How long to wait for connection attempt before giving up.</param>
        /// <param name="socketType">The <see cref="SocketType"/> to use for the dummy connection (defaults to <see cref="SocketType.Stream"/>).</param>
        /// <param name="protocolType">The <see cref="ProtocolType"/> to use for the dummy connection (defaults to <see cref="ProtocolType.Tcp"/>).</param>
        /// <returns>A task representing the ongoing connection attempt.</returns>
        internal static async Task AssertConnectivityAsync(this DnsEndPoint endPoint, string name, TimeSpan timeout,
                                                           SocketType socketType = SocketType.Stream, ProtocolType protocolType = ProtocolType.Tcp)
        {
            using (var socketAsyncEventArgs = new ConnectEventArgs())
            {
                using (var cancellationTokenSource = new CancellationTokenSource(timeout))
                {
                    try
                    {
                        socketAsyncEventArgs.Initialize(cancellationTokenSource.Token);
                        socketAsyncEventArgs.RemoteEndPoint = endPoint;

                        if (Socket.ConnectAsync(socketType, protocolType, socketAsyncEventArgs))
                        {
                            // Connect completing asynchronously. Enable it to be canceled and wait for it.
                            using (cancellationTokenSource.Token.Register(state => Socket.CancelConnectAsync((SocketAsyncEventArgs)state), socketAsyncEventArgs))
                            {
                                await socketAsyncEventArgs.Builder.Task.ConfigureAwait(false);
                            }
                        }
                        else if (socketAsyncEventArgs.SocketError != SocketError.Success)
                        {
                            // Connect completed synchronously but unsuccessfully.
                            throw new SocketException((int)socketAsyncEventArgs.SocketError);
                        }
                    }
                    catch (OperationCanceledException e)
                    {
                        throw new System.Exception($"Connection attempt to {name} host '{endPoint.Host}:{endPoint.Port}' timed out after {timeout.Seconds} seconds.", e);
                    }
                    catch (System.Exception e)
                    {
                        throw new System.Exception($"Connection attempt to {name} host '{endPoint.Host}:{endPoint.Port}' failed.", e);
                    }
                }
            }
        }
示例#23
0
        private void TryConnect(object sender)
        {
            int timeout = (int)sender;

            if (cancellationToken.IsCancellationRequested)
            {
                DebugLog.WriteLine("TcpConnection", "Connection to {0} cancelled by user", destination);
                Release(userRequestedDisconnect: true);
                return;
            }

            var connectEventArgs = new SocketAsyncEventArgs {
                RemoteEndPoint = destination
            };
            var asyncWaitHandle = new ManualResetEvent(initialState: false);
            EventHandler <SocketAsyncEventArgs> completionHandler = (s, e) =>
            {
                asyncWaitHandle.Set();

                var connected = e.ConnectSocket != null;
                ConnectCompleted(connected);
                (e as IDisposable)?.Dispose();
            };

            connectEventArgs.Completed += completionHandler;

            if (!socket.ConnectAsync(connectEventArgs))
            {
                completionHandler(socket, connectEventArgs);
            }

            if (WaitHandle.WaitAny(new WaitHandle[] { asyncWaitHandle, cancellationToken.Token.WaitHandle }, timeout) != 0)
            {
                Socket.CancelConnectAsync(connectEventArgs);
            }
        }
示例#24
0
        internal static async Task <Socket> ConnectAsync(IPEndPoint endPoint, ILogger logger, int timeout = -1, CancellationToken ct = default)
        {
            var socket    = Utilities.CreateSocket();
            var semaphore = new SemaphoreSlim(0, 1);

            void handler(object sender, SocketAsyncEventArgs a) => semaphore.Release();

            var args = new SocketAsyncEventArgs
            {
                RemoteEndPoint = endPoint
            };

            args.Completed += handler;

            try
            {
                ct.ThrowIfCancellationRequested();

                if (socket.ConnectAsync(args))
                {
                    if (!await semaphore.WaitAsync(timeout, ct).ConfigureAwait(false))
                    {
                        throw new SocketException((int)SocketError.TimedOut);
                    }
                }

                if (args.SocketError != SocketError.Success)
                {
                    throw new SocketException((int)args.SocketError);
                }

                return(socket);
            }
            catch (SocketException e)
            {
                var errorName = "SocketException: " + Enum.GetName(typeof(SocketError), e.ErrorCode);
                logger.LogInformation($"Socket at {socket.LocalEndPoint} could not connect to {endPoint}. {errorName}.\r\n{e}");
                throw;
            }
            catch (OperationCanceledException e)
            {
                logger.LogInformation($"Socket at {socket.LocalEndPoint} could not connect to {endPoint}. {e.Message}\r\n{e}");
                throw;
            }
            catch (Exception e)
            {
                logger.LogWarning($"Socket at {socket.LocalEndPoint} could not connect to {endPoint}. {e.Message}\r\n{e}");
                throw;
            }
            finally
            {
                args.Completed -= handler;
                args.Dispose();
                semaphore.Dispose();
                if (args.SocketError != SocketError.Success)
                {
                    Socket.CancelConnectAsync(args);
                    socket.Dispose();
                }
            }
        }
        /// <summary>
        ///		Establishes logical connection, which specified to the managed transport protocol, for the server.
        /// </summary>
        /// <param name="targetEndPoint">The end point of target server.</param>
        /// <returns>
        ///		<see cref="Task{T}"/> of <see cref="ClientTransport"/> which represents asynchronous establishment process specific to the managed transport.
        ///		This value will not be <c>null</c>.
        /// </returns>
        protected sealed override Task <ClientTransport> ConnectAsyncCore(EndPoint targetEndPoint)
        {
            TaskCompletionSource <ClientTransport> source = new TaskCompletionSource <ClientTransport>();
            var context = new SocketAsyncEventArgs();

            context.RemoteEndPoint = targetEndPoint;
            context.Completed     += this.OnCompleted;

#if !API_SIGNATURE_TEST
            MsgPackRpcClientProtocolsTrace.TraceEvent(
                MsgPackRpcClientProtocolsTrace.BeginConnect,
                "Connecting. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3} }}",
                targetEndPoint,
                targetEndPoint.AddressFamily,
                this.Configuration.PreferIPv4,
                Socket.OSSupportsIPv6
                );
#endif
#if MONO
            var connectingSocket = new Socket(targetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
#endif
            context.UserToken =
                Tuple.Create(
                    source,
                    this.BeginConnectTimeoutWatch(
                        () =>
            {
#if !API_SIGNATURE_TEST
                MsgPackRpcClientProtocolsTrace.TraceEvent(
                    MsgPackRpcClientProtocolsTrace.ConnectTimeout,
                    "Connect timeout. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3}, \"ConnectTimeout\" : {4} }}",
                    targetEndPoint,
                    targetEndPoint.AddressFamily,
                    this.Configuration.PreferIPv4,
                    Socket.OSSupportsIPv6,
                    this.Configuration.ConnectTimeout
                    );
#endif
#if MONO
                // Cancel ConnectAsync.
                connectingSocket.Close();
#else
                Socket.CancelConnectAsync(context);
#endif
            }
                        )
#if MONO
                    , connectingSocket
#endif
                    );

#if MONO
            if (!connectingSocket.ConnectAsync(context))
#else
            if (!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, context))
#endif
            {
                this.OnCompleted(null, context);
            }

            return(source.Task);
        }
 public void CancelConnectAsync_NullEventArgs_Throws_ArgumentNull()
 {
     Assert.Throws <ArgumentNullException>(() => Socket.CancelConnectAsync(null));
 }
示例#27
0
        /// <summary>
        /// Disconnect the client (synchronous)
        /// </summary>
        /// <returns>'true' if the client was successfully disconnected, 'false' if the client is already disconnected</returns>
        public virtual bool Disconnect()
        {
            if (!IsConnected && !IsConnecting)
            {
                return(false);
            }

            // Cancel connecting operation
            if (IsConnecting)
            {
                Socket.CancelConnectAsync(_connectEventArg);
            }

            if (_disconnecting)
            {
                return(false);
            }

            // Reset connecting & handshaking flags
            IsConnecting  = false;
            IsHandshaking = false;

            // Update the disconnecting flag
            _disconnecting = true;

            // Reset event args
            _connectEventArg.Completed -= OnAsyncCompleted;

            // Call the client disconnecting handler
            OnDisconnecting();

            try
            {
                try
                {
                    // Shutdown the SSL stream
                    _sslStream.ShutdownAsync().Wait();
                }
                catch (Exception) {}

                // Dispose the SSL stream & buffer
                _sslStream.Dispose();
                _sslStreamId = null;

                try
                {
                    // Shutdown the socket associated with the client
                    Socket.Shutdown(SocketShutdown.Both);
                }
                catch (SocketException) {}

                // Close the client socket
                Socket.Close();

                // Dispose the client socket
                Socket.Dispose();

                // Dispose event arguments
                _connectEventArg.Dispose();

                // Update the client socket disposed flag
                IsSocketDisposed = true;
            }
            catch (ObjectDisposedException) {}

            // Update the handshaked flag
            IsHandshaked = false;

            // Update the connected flag
            IsConnected = false;

            // Update sending/receiving flags
            _receiving = false;
            _sending   = false;

            // Clear send/receive buffers
            ClearBuffers();

            // Call the client disconnected handler
            OnDisconnected();

            // Reset the disconnecting flag
            _disconnecting = false;

            return(true);
        }
示例#28
0
 /// <summary>
 /// Cancels an asynchronous request for a remote host connection.
 /// </summary>
 /// <param name="e">The System.Net.Sockets.SocketAsyncEventArgs object used to request the connection to the remote host by calling one of the ConnectAsync methods.</param>
 public static void CancelConnectAsync(SocketAsyncEventArgs e)
 {
     Socket.CancelConnectAsync(e);
 }
示例#29
0
        public static async ValueTask <Stream> ConnectAsync(string host, int port, CancellationToken cancellationToken)
        {
            try
            {
                // Rather than creating a new Socket and calling ConnectAsync on it, we use the static
                // Socket.ConnectAsync with a SocketAsyncEventArgs, as we can then use Socket.CancelConnectAsync
                // to cancel it if needed.
                using (var saea = new BuilderAndCancellationTokenSocketAsyncEventArgs(cancellationToken))
                {
                    // Configure which server to which to connect.
                    saea.RemoteEndPoint = IPAddress.TryParse(host, out IPAddress address) ?
                                          (EndPoint) new IPEndPoint(address, port) :
                                          new DnsEndPoint(host, port);

                    // Hook up a callback that'll complete the Task when the operation completes.
                    saea.Completed += (s, e) =>
                    {
                        var csaea = (BuilderAndCancellationTokenSocketAsyncEventArgs)e;
                        switch (e.SocketError)
                        {
                        case SocketError.Success:
                            csaea.Builder.SetResult();
                            break;

                        case SocketError.OperationAborted:
                        case SocketError.ConnectionAborted:
                            if (csaea.CancellationToken.IsCancellationRequested)
                            {
                                csaea.Builder.SetException(new OperationCanceledException(csaea.CancellationToken));
                                break;
                            }
                            goto default;

                        default:
                            csaea.Builder.SetException(new SocketException((int)e.SocketError));
                            break;
                        }
                    };

                    // Initiate the connection.
                    if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, saea))
                    {
                        // Connect completing asynchronously. Enable it to be canceled and wait for it.
                        using (cancellationToken.Register(s => Socket.CancelConnectAsync((SocketAsyncEventArgs)s), saea))
                        {
                            await saea.Builder.Task.ConfigureAwait(false);
                        }
                    }
                    else if (saea.SocketError != SocketError.Success)
                    {
                        // Connect completed synchronously but unsuccessfully.
                        throw new SocketException((int)saea.SocketError);
                    }

                    Debug.Assert(saea.SocketError == SocketError.Success, $"Expected Success, got {saea.SocketError}.");
                    Debug.Assert(saea.ConnectSocket != null, "Expected non-null socket");
                    Debug.Assert(saea.ConnectSocket.Connected, "Expected socket to be connected");

                    // Configure the socket and return a stream for it.
                    Socket socket = saea.ConnectSocket;
                    socket.NoDelay = true;
                    return(new NetworkStream(socket, ownsSocket: true));
                }
            }
            catch (SocketException se)
            {
                throw new HttpRequestException(se.Message, se);
            }
        }