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(); } }
/// <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); }
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); }
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(); } } }
/// <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(); } }
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)); }
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); }
private void ConnectCancelled(ConnectToken token, SocketAsyncEventArgs e) { if (token.IsCompleted) { return; } Socket.CancelConnectAsync(e); if (token.IsCompleted) { return; } ((ConnectToken)e.UserToken).TrySetCanceled(); ClearConnect(e); }
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(); } }
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); } } }
/// <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(); } }
/// <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); }
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"); } } }
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); }
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); } } } }
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); } }
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)); }
/// <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); }
/// <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); }
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); } }