From 7b83178f4279f087fd2e347bdb3ffd6a1a050833 Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Sun, 22 Nov 2020 14:41:51 -0800 Subject: [PATCH 1/4] move SocketTaskExtensions methods to Socket class --- .../ref/System.Net.Sockets.cs | 38 ++++++++++++++++++ .../src/System/Net/Sockets/Socket.Tasks.cs | 40 +++++++++++-------- .../Net/Sockets/SocketTaskExtensions.cs | 26 ++++++++++-- .../ArgumentValidationTests.cs | 4 +- 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 781b6676f56656..3515e0e67084be 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -399,6 +399,25 @@ public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, Sy public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, int optionValue) { } public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, object optionValue) { } public void Shutdown(System.Net.Sockets.SocketShutdown how) { } + public System.Threading.Tasks.Task AcceptAsync() { throw null; } + public System.Threading.Tasks.Task AcceptAsync(System.Net.Sockets.Socket? acceptSocket) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(System.Net.EndPoint remoteEP) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress address, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress address, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress[] addresses, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress[] addresses, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(string host, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(string host, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.Task ReceiveAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public System.Threading.Tasks.Task ReceiveFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } + public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } + public System.Threading.Tasks.Task SendAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.Task SendAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.ValueTask SendAsync(System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public System.Threading.Tasks.Task SendToAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } } public partial class SocketAsyncEventArgs : System.EventArgs, System.IDisposable { @@ -552,24 +571,43 @@ public enum SocketShutdown } public static partial class SocketTaskExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task AcceptAsync(this System.Net.Sockets.Socket socket) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task AcceptAsync(this System.Net.Sockets.Socket socket, System.Net.Sockets.Socket? acceptSocket) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.EndPoint remoteEP) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.IPAddress address, int port) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.IPAddress address, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.IPAddress[] addresses, int port) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask ConnectAsync(this System.Net.Sockets.Socket socket, System.Net.IPAddress[] addresses, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ConnectAsync(this System.Net.Sockets.Socket socket, string host, int port) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask ConnectAsync(this System.Net.Sockets.Socket socket, string host, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ReceiveAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ReceiveAsync(this System.Net.Sockets.Socket socket, System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask ReceiveAsync(this System.Net.Sockets.Socket socket, System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ReceiveFromAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task ReceiveMessageFromAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task SendAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task SendAsync(this System.Net.Sockets.Socket socket, System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.ValueTask SendAsync(this System.Net.Sockets.Socket socket, System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static System.Threading.Tasks.Task SendToAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } } public enum SocketType diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs index 3f8e8a75fa55b3..ddab4cc59daa70 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs @@ -28,7 +28,9 @@ public partial class Socket /// Cached instance for send operations that return . private TaskSocketAsyncEventArgs? _multiBufferSendEventArgs; - internal Task AcceptAsync(Socket? acceptSocket) + public Task AcceptAsync() => AcceptAsync((Socket?)null); + + public Task AcceptAsync(Socket? acceptSocket) { // Get any cached SocketAsyncEventArg we may have. TaskSocketAsyncEventArgs? saea = Interlocked.Exchange(ref _acceptEventArgs, null); @@ -71,9 +73,9 @@ internal Task AcceptAsync(Socket? acceptSocket) return t; } - internal Task ConnectAsync(EndPoint remoteEP) => ConnectAsync(remoteEP, default).AsTask(); + public Task ConnectAsync(EndPoint remoteEP) => ConnectAsync(remoteEP, default).AsTask(); - internal ValueTask ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken) + public ValueTask ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -114,16 +116,15 @@ static async ValueTask WaitForConnectWithCancellation(AwaitableSocketAsyncEventA throw; } } - } - internal Task ConnectAsync(IPAddress address, int port) => ConnectAsync(new IPEndPoint(address, port)); + public Task ConnectAsync(IPAddress address, int port) => ConnectAsync(new IPEndPoint(address, port)); - internal ValueTask ConnectAsync(IPAddress address, int port, CancellationToken cancellationToken) => ConnectAsync(new IPEndPoint(address, port), cancellationToken); + public ValueTask ConnectAsync(IPAddress address, int port, CancellationToken cancellationToken) => ConnectAsync(new IPEndPoint(address, port), cancellationToken); - internal Task ConnectAsync(IPAddress[] addresses, int port) => ConnectAsync(addresses, port, CancellationToken.None).AsTask(); + public Task ConnectAsync(IPAddress[] addresses, int port) => ConnectAsync(addresses, port, CancellationToken.None).AsTask(); - internal ValueTask ConnectAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken) + public ValueTask ConnectAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -188,9 +189,9 @@ async ValueTask Core(IPAddress[] addresses, int port, CancellationToken cancella } } - internal Task ConnectAsync(string host, int port) => ConnectAsync(host, port, default).AsTask(); + public Task ConnectAsync(string host, int port) => ConnectAsync(host, port, default).AsTask(); - internal ValueTask ConnectAsync(string host, int port, CancellationToken cancellationToken) + public ValueTask ConnectAsync(string host, int port, CancellationToken cancellationToken) { if (host == null) { @@ -203,12 +204,17 @@ internal ValueTask ConnectAsync(string host, int port, CancellationToken cancell return ConnectAsync(ep, cancellationToken); } + public Task ReceiveAsync(ArraySegment buffer, SocketFlags socketFlags) => ReceiveAsync(buffer, socketFlags, fromNetworkStream: false); + internal Task ReceiveAsync(ArraySegment buffer, SocketFlags socketFlags, bool fromNetworkStream) { ValidateBuffer(buffer); return ReceiveAsync(buffer, socketFlags, fromNetworkStream, default).AsTask(); } + public ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlags, CancellationToken cancellationToken) => + ReceiveAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken); + internal ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlags, bool fromNetworkStream, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -227,7 +233,7 @@ internal ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlag return saea.ReceiveAsync(this, cancellationToken); } - internal Task ReceiveAsync(IList> buffers, SocketFlags socketFlags) + public Task ReceiveAsync(IList> buffers, SocketFlags socketFlags) { ValidateBuffersList(buffers); @@ -243,7 +249,7 @@ internal Task ReceiveAsync(IList> buffers, SocketFlags s return GetTaskForSendReceive(ReceiveAsync(saea), saea, fromNetworkStream: false, isReceive: true); } - internal Task ReceiveFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) + public Task ReceiveFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) { var tcs = new StateTaskCompletionSource(this) { _field1 = remoteEndPoint }; BeginReceiveFrom(buffer.Array!, buffer.Offset, buffer.Count, socketFlags, ref tcs._field1, iar => @@ -263,7 +269,7 @@ internal Task ReceiveFromAsync(ArraySegment buffe return tcs.Task; } - internal Task ReceiveMessageFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) + public Task ReceiveMessageFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) { var tcs = new StateTaskCompletionSource(this) { _field1 = socketFlags, _field2 = remoteEndPoint }; BeginReceiveMessageFrom(buffer.Array!, buffer.Offset, buffer.Count, socketFlags, ref tcs._field2, iar => @@ -286,13 +292,13 @@ internal Task ReceiveMessageFromAsync(ArraySegme return tcs.Task; } - internal Task SendAsync(ArraySegment buffer, SocketFlags socketFlags) + public Task SendAsync(ArraySegment buffer, SocketFlags socketFlags) { ValidateBuffer(buffer); return SendAsync(buffer, socketFlags, default).AsTask(); } - internal ValueTask SendAsync(ReadOnlyMemory buffer, SocketFlags socketFlags, CancellationToken cancellationToken) + public ValueTask SendAsync(ReadOnlyMemory buffer, SocketFlags socketFlags, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -328,7 +334,7 @@ internal ValueTask SendAsyncForNetworkStream(ReadOnlyMemory buffer, Socket return saea.SendAsyncForNetworkStream(this, cancellationToken); } - internal Task SendAsync(IList> buffers, SocketFlags socketFlags) + public Task SendAsync(IList> buffers, SocketFlags socketFlags) { ValidateBuffersList(buffers); @@ -344,7 +350,7 @@ internal Task SendAsync(IList> buffers, SocketFlags sock return GetTaskForSendReceive(SendAsync(saea), saea, fromNetworkStream: false, isReceive: false); } - internal Task SendToAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEP) + public Task SendToAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEP) { var tcs = new TaskCompletionSource(this); BeginSendTo(buffer.Array!, buffer.Offset, buffer.Count, socketFlags, remoteEP, iar => diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs index f6a2243e626df3..1d9a3d6826a621 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.ComponentModel; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -9,45 +10,64 @@ namespace System.Net.Sockets { public static class SocketTaskExtensions { + [EditorBrowsable(EditorBrowsableState.Never)] public static Task AcceptAsync(this Socket socket) => - socket.AcceptAsync((Socket?)null); + socket.AcceptAsync(); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task AcceptAsync(this Socket socket, Socket? acceptSocket) => socket.AcceptAsync(acceptSocket); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ConnectAsync(this Socket socket, EndPoint remoteEP) => socket.ConnectAsync(remoteEP); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask ConnectAsync(this Socket socket, EndPoint remoteEP, CancellationToken cancellationToken) => socket.ConnectAsync(remoteEP, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ConnectAsync(this Socket socket, IPAddress address, int port) => socket.ConnectAsync(address, port); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask ConnectAsync(this Socket socket, IPAddress address, int port, CancellationToken cancellationToken) => socket.ConnectAsync(address, port, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ConnectAsync(this Socket socket, IPAddress[] addresses, int port) => socket.ConnectAsync(addresses, port); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask ConnectAsync(this Socket socket, IPAddress[] addresses, int port, CancellationToken cancellationToken) => socket.ConnectAsync(addresses, port, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ConnectAsync(this Socket socket, string host, int port) => socket.ConnectAsync(host, port); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask ConnectAsync(this Socket socket, string host, int port, CancellationToken cancellationToken) => socket.ConnectAsync(host, port, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ReceiveAsync(this Socket socket, ArraySegment buffer, SocketFlags socketFlags) => - socket.ReceiveAsync(buffer, socketFlags, fromNetworkStream: false); + socket.ReceiveAsync(buffer, socketFlags); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask ReceiveAsync(this Socket socket, Memory buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => - socket.ReceiveAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken: cancellationToken); + socket.ReceiveAsync(buffer, socketFlags, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ReceiveAsync(this Socket socket, IList> buffers, SocketFlags socketFlags) => socket.ReceiveAsync(buffers, socketFlags); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ReceiveFromAsync(this Socket socket, ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) => socket.ReceiveFromAsync(buffer, socketFlags, remoteEndPoint); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task ReceiveMessageFromAsync(this Socket socket, ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) => socket.ReceiveMessageFromAsync(buffer, socketFlags, remoteEndPoint); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task SendAsync(this Socket socket, ArraySegment buffer, SocketFlags socketFlags) => socket.SendAsync(buffer, socketFlags); + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask SendAsync(this Socket socket, ReadOnlyMemory buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => socket.SendAsync(buffer, socketFlags, cancellationToken); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task SendAsync(this Socket socket, IList> buffers, SocketFlags socketFlags) => socket.SendAsync(buffers, socketFlags); + [EditorBrowsable(EditorBrowsableState.Never)] public static Task SendToAsync(this Socket socket, ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEP) => socket.SendToAsync(buffer, socketFlags, remoteEP); } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs index accf15c3ec7f5b..003c7fdbbc611b 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs @@ -505,7 +505,7 @@ public void Select_LargeList_Throws_ArgumentOutOfRange() [Fact] public void AcceptAsync_NullAsyncEventArgs_Throws_ArgumentNull() { - Assert.Throws(() => GetSocket().AcceptAsync(null)); + Assert.Throws(() => GetSocket().AcceptAsync((SocketAsyncEventArgs)null)); } [Fact] @@ -537,7 +537,7 @@ public void AcceptAsync_NotListening_Throws_InvalidOperation() [Fact] public void ConnectAsync_NullAsyncEventArgs_Throws_ArgumentNull() { - Assert.Throws(() => GetSocket().ConnectAsync(null)); + Assert.Throws(() => GetSocket().ConnectAsync((SocketAsyncEventArgs)null)); } [Fact] From 968de897cd709a92c4de7ff8372c78c0f6c8bf5c Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Sun, 22 Nov 2020 19:02:33 -0800 Subject: [PATCH 2/4] add SocketTaskExtensionsTest for minimal verification of the old extension methods --- .../SocketTaskExtensionsTest.cs | 47 +++++++++++++++++++ .../System.Net.Sockets.Tests.csproj | 1 + 2 files changed, 48 insertions(+) create mode 100644 src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTaskExtensionsTest.cs diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTaskExtensionsTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTaskExtensionsTest.cs new file mode 100644 index 00000000000000..bdc7ec7e3ef0f3 --- /dev/null +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTaskExtensionsTest.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading; +using System.Threading.Tasks; + +using Xunit; + +namespace System.Net.Sockets.Tests +{ + public class SocketTaskExtensionsTest + { + [Fact] + public async Task EnsureMethodsAreCallable() + { + // The purpose of this test is just to ensure that the now-hidden extension methods in SocketTaskExtensions are + // properly invoking the underlying instance methods, and not accidentally binding to themselves, causing infinite recursion. + Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint badEndPoint = new IPEndPoint(IPAddress.None, 0); + string badHostName = "nosuchhost.invalid"; + byte[] buffer = new byte[1]; + + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.AcceptAsync(s)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.AcceptAsync(s, null)); + + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badEndPoint)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badEndPoint, CancellationToken.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badEndPoint.Address, badEndPoint.Port)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badEndPoint.Address, badEndPoint.Port, CancellationToken.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, new IPAddress[] { badEndPoint.Address, badEndPoint.Address }, badEndPoint.Port)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, new IPAddress[] { badEndPoint.Address, badEndPoint.Address }, badEndPoint.Port, CancellationToken.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badHostName, badEndPoint.Port)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ConnectAsync(s, badHostName, badEndPoint.Port, CancellationToken.None)); + + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ReceiveAsync(s, new ArraySegment(buffer), SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ReceiveAsync(s, buffer.AsMemory(), SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ReceiveAsync(s, new ArraySegment[] { new ArraySegment(buffer) }, SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ReceiveFromAsync(s, new ArraySegment(buffer), SocketFlags.None, badEndPoint)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.ReceiveMessageFromAsync(s, new ArraySegment(buffer), SocketFlags.None, badEndPoint)); + + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.SendAsync(s, new ArraySegment(buffer), SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.SendAsync(s, buffer.AsMemory(), SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.SendAsync(s, new ArraySegment[] { new ArraySegment(buffer) }, SocketFlags.None)); + await Assert.ThrowsAsync(async () => await SocketTaskExtensions.SendToAsync(s, new ArraySegment(buffer), SocketFlags.None, badEndPoint)); + } + } +} diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index e2522c8009bcb7..bda9103731e62f 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -52,6 +52,7 @@ + From 9f1ed2f950af0ba960e9b571e2139ab26d93c2cb Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Tue, 24 Nov 2020 09:58:36 -0800 Subject: [PATCH 3/4] alphabetize methods in ref source --- .../ref/System.Net.Sockets.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 3515e0e67084be..9f1e8403036358 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -290,6 +290,8 @@ public Socket(System.Net.Sockets.SocketType socketType, System.Net.Sockets.Proto public short Ttl { get { throw null; } set { } } public bool UseOnlyOverlappedIO { get { throw null; } set { } } public System.Net.Sockets.Socket Accept() { throw null; } + public System.Threading.Tasks.Task AcceptAsync() { throw null; } + public System.Threading.Tasks.Task AcceptAsync(System.Net.Sockets.Socket? acceptSocket) { throw null; } public bool AcceptAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public System.IAsyncResult BeginAccept(System.AsyncCallback? callback, object? state) { throw null; } public System.IAsyncResult BeginAccept(int receiveSize, System.AsyncCallback? callback, object? state) { throw null; } @@ -320,6 +322,14 @@ public void Connect(System.Net.EndPoint remoteEP) { } public void Connect(System.Net.IPAddress address, int port) { } public void Connect(System.Net.IPAddress[] addresses, int port) { } public void Connect(string host, int port) { } + public System.Threading.Tasks.Task ConnectAsync(System.Net.EndPoint remoteEP) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress address, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress address, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress[] addresses, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress[] addresses, int port, System.Threading.CancellationToken cancellationToken) { throw null; } + public System.Threading.Tasks.Task ConnectAsync(string host, int port) { throw null; } + public System.Threading.Tasks.ValueTask ConnectAsync(string host, int port, System.Threading.CancellationToken cancellationToken) { throw null; } public bool ConnectAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public static bool ConnectAsync(System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType, System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public void Disconnect(bool reuseSocket) { } @@ -362,13 +372,18 @@ public void Listen(int backlog) { } public int Receive(System.Span buffer) { throw null; } public int Receive(System.Span buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } public int Receive(System.Span buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) { throw null; } + public System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.Task ReceiveAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public bool ReceiveAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public int ReceiveFrom(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) { throw null; } public int ReceiveFrom(byte[] buffer, int size, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) { throw null; } public int ReceiveFrom(byte[] buffer, ref System.Net.EndPoint remoteEP) { throw null; } public int ReceiveFrom(byte[] buffer, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) { throw null; } + public System.Threading.Tasks.Task ReceiveFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } public bool ReceiveFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } + public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } public bool ReceiveMessageFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public static void Select(System.Collections.IList? checkRead, System.Collections.IList? checkWrite, System.Collections.IList? checkError, int microSeconds) { } public int Send(byte[] buffer) { throw null; } @@ -382,6 +397,9 @@ public static void Select(System.Collections.IList? checkRead, System.Collection public int Send(System.ReadOnlySpan buffer) { throw null; } public int Send(System.ReadOnlySpan buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } public int Send(System.ReadOnlySpan buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) { throw null; } + public System.Threading.Tasks.Task SendAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.Task SendAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } + public System.Threading.Tasks.ValueTask SendAsync(System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public bool SendAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public void SendFile(string? fileName) { } public void SendFile(string? fileName, byte[]? preBuffer, byte[]? postBuffer, System.Net.Sockets.TransmitFileOptions flags) { } @@ -390,6 +408,7 @@ public void SendFile(string? fileName, byte[]? preBuffer, byte[]? postBuffer, Sy public int SendTo(byte[] buffer, int size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } public int SendTo(byte[] buffer, System.Net.EndPoint remoteEP) { throw null; } public int SendTo(byte[] buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } + public System.Threading.Tasks.Task SendToAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } public bool SendToAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public void SetIPProtectionLevel(System.Net.Sockets.IPProtectionLevel level) { } @@ -399,25 +418,6 @@ public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, Sy public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, int optionValue) { } public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, object optionValue) { } public void Shutdown(System.Net.Sockets.SocketShutdown how) { } - public System.Threading.Tasks.Task AcceptAsync() { throw null; } - public System.Threading.Tasks.Task AcceptAsync(System.Net.Sockets.Socket? acceptSocket) { throw null; } - public System.Threading.Tasks.Task ConnectAsync(System.Net.EndPoint remoteEP) { throw null; } - public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken) { throw null; } - public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress address, int port) { throw null; } - public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress address, int port, System.Threading.CancellationToken cancellationToken) { throw null; } - public System.Threading.Tasks.Task ConnectAsync(System.Net.IPAddress[] addresses, int port) { throw null; } - public System.Threading.Tasks.ValueTask ConnectAsync(System.Net.IPAddress[] addresses, int port, System.Threading.CancellationToken cancellationToken) { throw null; } - public System.Threading.Tasks.Task ConnectAsync(string host, int port) { throw null; } - public System.Threading.Tasks.ValueTask ConnectAsync(string host, int port, System.Threading.CancellationToken cancellationToken) { throw null; } - public System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } - public System.Threading.Tasks.Task ReceiveAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } - public System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.Task ReceiveFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } - public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } - public System.Threading.Tasks.Task SendAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; } - public System.Threading.Tasks.Task SendAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) { throw null; } - public System.Threading.Tasks.ValueTask SendAsync(System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.Task SendToAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; } } public partial class SocketAsyncEventArgs : System.EventArgs, System.IDisposable { From 9f731887a78545c6b59401ed2eb549e85670cb6d Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Tue, 15 Dec 2020 13:01:02 -0800 Subject: [PATCH 4/4] add doc comments --- .../src/System/Net/Sockets/Socket.Tasks.cs | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs index ddab4cc59daa70..07cc7af8128c48 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs @@ -28,8 +28,17 @@ public partial class Socket /// Cached instance for send operations that return . private TaskSocketAsyncEventArgs? _multiBufferSendEventArgs; + /// + /// Accepts an incoming connection. + /// + /// An asynchronous task that completes with the accepted Socket. public Task AcceptAsync() => AcceptAsync((Socket?)null); + /// + /// Accepts an incoming connection. + /// + /// The socket to use for accepting the connection. + /// An asynchronous task that completes with the accepted Socket. public Task AcceptAsync(Socket? acceptSocket) { // Get any cached SocketAsyncEventArg we may have. @@ -73,8 +82,19 @@ public Task AcceptAsync(Socket? acceptSocket) return t; } + /// + /// Establishes a connection to a remote host. + /// + /// The endpoint to connect to. + /// An asynchronous task that completes when the connection is established. public Task ConnectAsync(EndPoint remoteEP) => ConnectAsync(remoteEP, default).AsTask(); + /// + /// Establishes a connection to a remote host. + /// + /// The endpoint to connect to. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes when the connection is established. public ValueTask ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -118,12 +138,38 @@ static async ValueTask WaitForConnectWithCancellation(AwaitableSocketAsyncEventA } } + /// + /// Establishes a connection to a remote host. + /// + /// The IPAddress of the remote host to connect to. + /// The port on the remote host to connect to. + /// An asynchronous task that completes when the connection is established. public Task ConnectAsync(IPAddress address, int port) => ConnectAsync(new IPEndPoint(address, port)); + /// + /// Establishes a connection to a remote host. + /// + /// The IPAddress of the remote host to connect to. + /// The port on the remote host to connect to. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes when the connection is established. public ValueTask ConnectAsync(IPAddress address, int port, CancellationToken cancellationToken) => ConnectAsync(new IPEndPoint(address, port), cancellationToken); + /// + /// Establishes a connection to a remote host. + /// + /// A list of IPAddresses for the remote host that will be used to attempt to connect to the remote host. + /// The port on the remote host to connect to. + /// An asynchronous task that completes when the connection is established. public Task ConnectAsync(IPAddress[] addresses, int port) => ConnectAsync(addresses, port, CancellationToken.None).AsTask(); + /// + /// Establishes a connection to a remote host. + /// + /// A list of IPAddresses for the remote host that will be used to attempt to connect to the remote host. + /// The port on the remote host to connect to. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes when the connection is established. public ValueTask ConnectAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -189,8 +235,21 @@ async ValueTask Core(IPAddress[] addresses, int port, CancellationToken cancella } } + /// + /// Establishes a connection to a remote host. + /// + /// The hostname of the remote host to connect to. + /// The port on the remote host to connect to. + /// An asynchronous task that completes when the connection is established. public Task ConnectAsync(string host, int port) => ConnectAsync(host, port, default).AsTask(); + /// + /// Establishes a connection to a remote host. + /// + /// The hostname of the remote host to connect to. + /// The port on the remote host to connect to. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes when the connection is established. public ValueTask ConnectAsync(string host, int port, CancellationToken cancellationToken) { if (host == null) @@ -204,6 +263,12 @@ public ValueTask ConnectAsync(string host, int port, CancellationToken cancellat return ConnectAsync(ep, cancellationToken); } + /// + /// Receives data from a connected socket. + /// + /// The buffer for the received data. + /// A bitwise combination of SocketFlags values that will be used when receiving the data. + /// An asynchronous task that completes with the number of bytes received. public Task ReceiveAsync(ArraySegment buffer, SocketFlags socketFlags) => ReceiveAsync(buffer, socketFlags, fromNetworkStream: false); internal Task ReceiveAsync(ArraySegment buffer, SocketFlags socketFlags, bool fromNetworkStream) @@ -212,6 +277,13 @@ internal Task ReceiveAsync(ArraySegment buffer, SocketFlags socketFla return ReceiveAsync(buffer, socketFlags, fromNetworkStream, default).AsTask(); } + /// + /// Receives data from a connected socket. + /// + /// The buffer for the received data. + /// A bitwise combination of SocketFlags values that will be used when receiving the data. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes with the number of bytes received. public ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlags, CancellationToken cancellationToken) => ReceiveAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken); @@ -233,6 +305,12 @@ internal ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlag return saea.ReceiveAsync(this, cancellationToken); } + /// + /// Receives data from a connected socket. + /// + /// A list of buffers for the received data. + /// A bitwise combination of SocketFlags values that will be used when receiving the data. + /// An asynchronous task that completes with the number of bytes received. public Task ReceiveAsync(IList> buffers, SocketFlags socketFlags) { ValidateBuffersList(buffers); @@ -249,6 +327,13 @@ public Task ReceiveAsync(IList> buffers, SocketFlags soc return GetTaskForSendReceive(ReceiveAsync(saea), saea, fromNetworkStream: false, isReceive: true); } + /// + /// Receives data and returns the endpoint of the sending host. + /// + /// The buffer for the received data. + /// A bitwise combination of SocketFlags values that will be used when receiving the data. + /// An endpoint of the same type as the endpoint of the remote host. + /// An asynchronous task that completes with a SocketReceiveFromResult containing the number of bytes received and the endpoint of the sending host. public Task ReceiveFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) { var tcs = new StateTaskCompletionSource(this) { _field1 = remoteEndPoint }; @@ -269,6 +354,13 @@ public Task ReceiveFromAsync(ArraySegment buffer, return tcs.Task; } + /// + /// Receives data and returns additional information about the sender of the message. + /// + /// The buffer for the received data. + /// A bitwise combination of SocketFlags values that will be used when receiving the data. + /// An endpoint of the same type as the endpoint of the remote host. + /// An asynchronous task that completes with a SocketReceiveMessageFromResult containing the number of bytes received and additional information about the sending host. public Task ReceiveMessageFromAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) { var tcs = new StateTaskCompletionSource(this) { _field1 = socketFlags, _field2 = remoteEndPoint }; @@ -292,12 +384,25 @@ public Task ReceiveMessageFromAsync(ArraySegment return tcs.Task; } + /// + /// Sends data on a connected socket. + /// + /// The buffer for the data to send. + /// A bitwise combination of SocketFlags values that will be used when sending the data. + /// An asynchronous task that completes with the number of bytes sent. public Task SendAsync(ArraySegment buffer, SocketFlags socketFlags) { ValidateBuffer(buffer); return SendAsync(buffer, socketFlags, default).AsTask(); } + /// + /// Sends data on a connected socket. + /// + /// The buffer for the data to send. + /// A bitwise combination of SocketFlags values that will be used when sending the data. + /// A cancellation token that can be used to cancel the asynchronous operation. + /// An asynchronous task that completes with the number of bytes sent. public ValueTask SendAsync(ReadOnlyMemory buffer, SocketFlags socketFlags, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -334,6 +439,12 @@ internal ValueTask SendAsyncForNetworkStream(ReadOnlyMemory buffer, Socket return saea.SendAsyncForNetworkStream(this, cancellationToken); } + /// + /// Sends data on a connected socket. + /// + /// A list of buffers for the data to send. + /// A bitwise combination of SocketFlags values that will be used when sending the data. + /// An asynchronous task that completes with the number of bytes sent. public Task SendAsync(IList> buffers, SocketFlags socketFlags) { ValidateBuffersList(buffers); @@ -350,6 +461,13 @@ public Task SendAsync(IList> buffers, SocketFlags socket return GetTaskForSendReceive(SendAsync(saea), saea, fromNetworkStream: false, isReceive: false); } + /// + /// Sends data to the specified remote host. + /// + /// The buffer for the data to send. + /// A bitwise combination of SocketFlags values that will be used when sending the data. + /// The remote host to which to send the data. + /// An asynchronous task that completes with the number of bytes sent. public Task SendToAsync(ArraySegment buffer, SocketFlags socketFlags, EndPoint remoteEP) { var tcs = new TaskCompletionSource(this);