Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@ -2,8 +2,10 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.2.0.0</AssemblyVersion>
<AssemblyVersion>4.2.1.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsNETCoreApp>true</IsNETCoreApp>
<IsUAP>true</IsUAP>
<IsNetFxNETStandard>true</IsNetFxNETStandard>
</PropertyGroup>
</Project>

View File

@ -4,6 +4,7 @@
<BuildConfigurations>
netcoreapp;
uap;
netfx;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -3,20 +3,27 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{834E3534-6A11-4A8D-923F-35C1E71CCEC3}</ProjectGuid>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System.Net.Sockets.cs" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
<ProjectReference Include="..\..\System.IO\ref\System.IO.csproj" />
<ProjectReference Include="..\..\System.IO.FileSystem.Primitives\ref\System.IO.FileSystem.Primitives.csproj" />
<ProjectReference Include="..\..\System.Net.Primitives\ref\System.Net.Primitives.csproj" />
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Threading.Tasks\ref\System.Threading.Tasks.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
<Reference Include="mscorlib" />
<Reference Include="System" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@ -5,6 +5,7 @@
uap-Windows_NT;
netcoreapp-Unix;
netcoreapp-Windows_NT;
netfx-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -223,4 +223,13 @@
<data name="net_io_readwritefailure" xml:space="preserve">
<value>Unable to transfer data on the transport connection: {0}.</value>
</data>
<data name="PlatformNotSupported_AcceptSocket" xml:space="preserve">
<value>Accepting into an existing Socket is not supported on this platform.</value>
</data>
<data name="PlatformNotSupported_IOControl" xml:space="preserve">
<value>Socket.IOControl handles Windows-specific control codes and is not supported on this platform.</value>
</data>
<data name="PlatformNotSupported_IPProtectionLevel" xml:space="preserve">
<value>IP protection level cannot be controlled on this platform.</value>
</data>
</root>

View File

@ -6,14 +6,17 @@
<ProjectGuid>{43311AFB-D7C4-4E5A-B1DE-855407F90D1B}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition="'$(TargetGroup)' == 'uap'">$(DefineConstants);uap</DefineConstants>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
<OmitResources Condition="'$(TargetGroup)' == 'netfx'">true</OmitResources>
</PropertyGroup>
<!-- Help VS understand available configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup>
<!-- SYSTEM_NET_SOCKETS_DLL is required to allow source-level code sharing for types defined within the
System.Net.Internals namespace. -->
@ -21,13 +24,15 @@
</PropertyGroup>
<ItemGroup>
<!-- All configurations -->
<Compile Include="System\Net\Sockets\TransmitFileOptions.cs" />
<Compile Include="System\Net\Sockets\SocketReceiveFromResult.cs" />
<Compile Include="System\Net\Sockets\SocketReceiveMessageFromResult.cs" />
<Compile Include="System\Net\Sockets\SocketTaskExtensions.cs" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
<Compile Include="System\Net\Sockets\SocketTaskExtensions.netfx.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
<!-- CoreCLR (All Operating Systems), .NET Native -->
<Compile Include="System\Net\Sockets\SocketTaskExtensions.cs" />
<Compile Include="System\Net\SocketPerfCounters.cs" />
<Compile Include="System\Net\Sockets\IOControlCode.cs" />
<Compile Include="System\Net\Sockets\IPPacketInformation.cs" />
@ -50,9 +55,9 @@
<Compile Include="System\Net\Sockets\SocketShutdown.cs" />
<Compile Include="System\Net\Sockets\TCPClient.cs" />
<Compile Include="System\Net\Sockets\TCPListener.cs" />
<Compile Include="System\Net\Sockets\TransmitFileOptions.cs" />
<Compile Include="System\Net\Sockets\TransportType.cs" />
<Compile Include="System\Net\Sockets\UDPClient.cs" />
<Compile Include="System\Net\Sockets\UDPClient.netstandard.cs" />
<Compile Include="System\Net\Sockets\UdpReceiveResult.cs" />
<Compile Include="System\Net\Sockets\AcceptOverlappedAsyncResult.cs" />
<Compile Include="System\Net\Sockets\BaseOverlappedAsyncResult.cs" />
@ -129,7 +134,7 @@
<Link>Common\System\Net\Sockets\SocketType.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsWindows)' == 'true'">
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'netfx'">
<!-- Windows: CoreCLR and .NET Native -->
<Compile Include="System\Net\Sockets\AcceptOverlappedAsyncResult.Windows.cs" />
<Compile Include="System\Net\Sockets\BaseOverlappedAsyncResult.Windows.cs" />
@ -244,7 +249,7 @@
</Compile>
</ItemGroup>
<!-- Windows : Win32 only -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'uap'">
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'uap' AND '$(TargetGroup)' != 'netfx'">
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetFileCompletionNotificationModes.cs">
<Link>Interop\Windows\kernel32\Interop.SetFileCompletionNotificationModes.cs</Link>
</Compile>
@ -398,7 +403,7 @@
<Link>Interop\Unix\System.Native\Interop.Write.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="System.Buffers" />
<Reference Include="System.Collections" />
@ -420,5 +425,9 @@
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
<Reference Include="System.Threading.ThreadPool" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
<Reference Include="mscorlib" />
<Reference Include="System" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>

View File

@ -261,6 +261,7 @@ namespace System.Net.Sockets
}
}
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal unsafe delegate bool AcceptExDelegate(
SafeCloseSocket listenSocketHandle,
SafeCloseSocket acceptSocketHandle,
@ -271,6 +272,7 @@ namespace System.Net.Sockets
out int bytesReceived,
NativeOverlapped* overlapped);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal delegate void GetAcceptExSockaddrsDelegate(
IntPtr buffer,
int receiveDataLength,
@ -282,6 +284,7 @@ namespace System.Net.Sockets
out int remoteSocketAddressLength);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal unsafe delegate bool ConnectExDelegate(
SafeCloseSocket socketHandle,
IntPtr socketAddress,
@ -291,18 +294,21 @@ namespace System.Net.Sockets
out int bytesSent,
NativeOverlapped* overlapped);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal unsafe delegate bool DisconnectExDelegate(
SafeCloseSocket socketHandle,
NativeOverlapped* overlapped,
int flags,
int reserved);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal delegate bool DisconnectExDelegateBlocking(
SafeCloseSocket socketHandle,
IntPtr overlapped,
int flags,
int reserved);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal unsafe delegate SocketError WSARecvMsgDelegate(
SafeCloseSocket socketHandle,
IntPtr msg,
@ -310,6 +316,7 @@ namespace System.Net.Sockets
NativeOverlapped* overlapped,
IntPtr completionRoutine);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal delegate SocketError WSARecvMsgDelegateBlocking(
IntPtr socketHandle,
IntPtr msg,
@ -317,6 +324,7 @@ namespace System.Net.Sockets
IntPtr overlapped,
IntPtr completionRoutine);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
internal unsafe delegate bool TransmitPacketsDelegate(
SafeCloseSocket socketHandle,
IntPtr packetArray,

View File

@ -323,7 +323,7 @@ namespace System.Net.Sockets
}
else
{
ExceptionDispatchInfo.Capture(e).Throw();
ExceptionDispatchInfo.Throw(e);
}
}

View File

@ -922,7 +922,8 @@ namespace System.Net.Sockets
/// <summary>Queues the provided continuation to be executed once the operation has completed.</summary>
public void OnCompleted(Action continuation)
{
if (_continuation == s_completedSentinel || Interlocked.CompareExchange(ref _continuation, continuation, null) == s_completedSentinel)
if (ReferenceEquals(_continuation, s_completedSentinel) ||
ReferenceEquals(Interlocked.CompareExchange(ref _continuation, continuation, null), s_completedSentinel))
{
Task.Run(continuation);
}

View File

@ -464,7 +464,7 @@ namespace System.Net.Sockets
{
// Get any cached, successfully-completed cached task that may exist on this SAEA.
Task<int> lastTask = saea._successfullyCompletedTask;
Debug.Assert(lastTask == null || lastTask.Status == TaskStatus.RanToCompletion);
Debug.Assert(lastTask == null || lastTask.IsCompletedSuccessfully);
// If there is a task and if it has the desired result, simply reuse it.
// Otherwise, create a new one for this result value, and in addition to returning it,

View File

@ -106,7 +106,7 @@ namespace System.Net.Sockets
// AcceptSocket is not supported on Unix.
if (acceptSocket != null)
{
throw new PlatformNotSupportedException();
throw new PlatformNotSupportedException(SR.PlatformNotSupported_AcceptSocket);
}
handle = null;

View File

@ -1 +1 @@
459f12c0130b79d654ebb0a2961a4e07bdc6ed37
c07087cce038e6a59b3d3a584b6fd28bf65a5be4

View File

@ -1385,6 +1385,7 @@ namespace System.Net.Sockets
Flags = flags,
SocketAddress = socketAddress,
SocketAddressLen = socketAddressLen,
BytesTransferred = bytesSent
};
bool isStopped;

View File

@ -46,16 +46,29 @@ namespace System.Net.Sockets
}
}
private const int EventBufferCount = 64;
private const int EventBufferCount =
#if DEBUG
32;
#else
1024;
#endif
private static readonly object s_lock = new object();
// In debug builds, force there to be 2 engines. In release builds, use half the number of processors when
// there are at least 6. The lower bound is to avoid using multiple engines on systems which aren't servers.
private static readonly int EngineCount =
#if DEBUG
2;
#else
Environment.ProcessorCount >= 6 ? Environment.ProcessorCount / 2 : 1;
#endif
//
// The current engine. We replace this with a new engine when we run out of "handle" values for the current
// engine.
// The current engines. We replace an engine when it runs out of "handle" values.
// Must be accessed under s_lock.
//
private static SocketAsyncEngine s_currentEngine;
private static readonly SocketAsyncEngine[] s_currentEngines = new SocketAsyncEngine[EngineCount];
private static int s_allocateFromEngine = 0;
private readonly IntPtr _port;
private readonly Interop.Sys.SocketEvent* _buffer;
@ -89,6 +102,7 @@ namespace System.Net.Sockets
//
private static readonly IntPtr MaxHandles = IntPtr.Size == 4 ? (IntPtr)int.MaxValue : (IntPtr)long.MaxValue;
#endif
private static readonly IntPtr MinHandlesForAdditionalEngine = EngineCount == 1 ? MaxHandles : (IntPtr)32;
//
// Sentinel handle value to identify events from the "shutdown pipe," used to signal an event loop to stop
@ -120,6 +134,16 @@ namespace System.Net.Sockets
//
private bool IsFull { get { return _nextHandle == MaxHandles; } }
// True if we've don't have sufficient active sockets to allow allocating a new engine.
private bool HasLowNumberOfSockets
{
get
{
return IntPtr.Size == 4 ? _outstandingHandles.ToInt32() < MinHandlesForAdditionalEngine.ToInt32() :
_outstandingHandles.ToInt64() < MinHandlesForAdditionalEngine.ToInt64();
}
}
//
// Allocates a new {SocketAsyncEngine, handle} pair.
//
@ -127,13 +151,39 @@ namespace System.Net.Sockets
{
lock (s_lock)
{
if (s_currentEngine == null)
engine = s_currentEngines[s_allocateFromEngine];
if (engine == null)
{
s_currentEngine = new SocketAsyncEngine();
// We minimize the number of engines on applications that have a low number of concurrent sockets.
for (int i = 0; i < s_allocateFromEngine; i++)
{
var previousEngine = s_currentEngines[i];
if (previousEngine == null || previousEngine.HasLowNumberOfSockets)
{
s_allocateFromEngine = i;
engine = previousEngine;
break;
}
}
if (engine == null)
{
s_currentEngines[s_allocateFromEngine] = engine = new SocketAsyncEngine();
}
}
engine = s_currentEngine;
handle = s_currentEngine.AllocateHandle(context);
handle = engine.AllocateHandle(context);
if (engine.IsFull)
{
// We'll need to create a new event port for the next handle.
s_currentEngines[s_allocateFromEngine] = null;
}
// Round-robin to the next engine once we have sufficient sockets on this one.
if (!engine.HasLowNumberOfSockets)
{
s_allocateFromEngine = (s_allocateFromEngine + 1) % EngineCount;
}
}
}
@ -148,12 +198,6 @@ namespace System.Net.Sockets
_nextHandle = IntPtr.Add(_nextHandle, 1);
_outstandingHandles = IntPtr.Add(_outstandingHandles, 1);
if (IsFull)
{
// We'll need to create a new event port for the next handle.
s_currentEngine = null;
}
Debug.Assert(handle != ShutdownHandle, $"Expected handle != ShutdownHandle: {handle}");
return handle;
}

View File

@ -301,7 +301,7 @@ namespace System.Net.Sockets
{
// Single buffer case.
socketError = Interop.Winsock.WSARecv(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref _wsaBuffer,
1,
out bytesTransferred,
@ -313,7 +313,7 @@ namespace System.Net.Sockets
{
// Multi buffer case.
socketError = Interop.Winsock.WSARecv(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
_wsaBufferArray,
_bufferListInternal.Count,
out bytesTransferred,
@ -321,6 +321,7 @@ namespace System.Net.Sockets
overlapped,
IntPtr.Zero);
}
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
return socketError;
@ -364,7 +365,7 @@ namespace System.Net.Sockets
if (_buffer != null)
{
socketError = Interop.Winsock.WSARecvFrom(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref _wsaBuffer,
1,
out bytesTransferred,
@ -377,7 +378,7 @@ namespace System.Net.Sockets
else
{
socketError = Interop.Winsock.WSARecvFrom(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
_wsaBufferArray,
_bufferListInternal.Count,
out bytesTransferred,
@ -387,6 +388,7 @@ namespace System.Net.Sockets
overlapped,
IntPtr.Zero);
}
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
return socketError;
@ -539,7 +541,7 @@ namespace System.Net.Sockets
{
// Single buffer case.
socketError = Interop.Winsock.WSASend(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref _wsaBuffer,
1,
out bytesTransferred,
@ -551,7 +553,7 @@ namespace System.Net.Sockets
{
// Multi buffer case.
socketError = Interop.Winsock.WSASend(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
_wsaBufferArray,
_bufferListInternal.Count,
out bytesTransferred,
@ -559,6 +561,7 @@ namespace System.Net.Sockets
overlapped,
IntPtr.Zero);
}
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
return socketError;
@ -713,7 +716,7 @@ namespace System.Net.Sockets
{
// Single buffer case.
socketError = Interop.Winsock.WSASendTo(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref _wsaBuffer,
1,
out bytesTransferred,
@ -726,7 +729,7 @@ namespace System.Net.Sockets
else
{
socketError = Interop.Winsock.WSASendTo(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
_wsaBufferArray,
_bufferListInternal.Count,
out bytesTransferred,
@ -736,6 +739,7 @@ namespace System.Net.Sockets
overlapped,
IntPtr.Zero);
}
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
return socketError;

View File

@ -88,7 +88,13 @@ namespace System.Net.Sockets
IOVectorCount = 1
};
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
errno = Interop.Sys.ReceiveMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&received);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
receivedFlags = messageHeader.Flags;
sockAddrLen = messageHeader.SocketAddressLen;
}
@ -128,7 +134,12 @@ namespace System.Net.Sockets
};
long bytesSent;
errno = Interop.Sys.SendMessage(socket, &messageHeader, flags, &bytesSent);
errno = Interop.Sys.SendMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&bytesSent);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
sent = checked((int)bytesSent);
}
@ -187,7 +198,12 @@ namespace System.Net.Sockets
};
long bytesSent;
errno = Interop.Sys.SendMessage(socket, &messageHeader, flags, &bytesSent);
errno = Interop.Sys.SendMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&bytesSent);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
sent = checked((int)bytesSent);
}
@ -232,12 +248,6 @@ namespace System.Net.Sockets
{
long bytesSent;
errno = Interop.Sys.SendFile(socket, fileHandle, offset, count, out bytesSent);
if (errno != Interop.Error.SUCCESS)
{
return -1;
}
offset += bytesSent;
count -= bytesSent;
return bytesSent;
@ -311,7 +321,13 @@ namespace System.Net.Sockets
IOVectorCount = iovCount
};
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
errno = Interop.Sys.ReceiveMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&received);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
receivedFlags = messageHeader.Flags;
sockAddrLen = messageHeader.SocketAddressLen;
}
@ -368,7 +384,13 @@ namespace System.Net.Sockets
ControlBufferLen = cmsgBufferLen
};
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
errno = Interop.Sys.ReceiveMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&received);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
receivedFlags = messageHeader.Flags;
sockAddrLen = messageHeader.SocketAddressLen;
ipPacketInformation = GetIPPacketInformation(&messageHeader, isIPv4, isIPv6);
@ -424,7 +446,13 @@ namespace System.Net.Sockets
};
long received;
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
errno = Interop.Sys.ReceiveMessage(
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
&messageHeader,
flags,
&received);
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
receivedFlags = messageHeader.Flags;
int sockAddrLen = messageHeader.SocketAddressLen;
ipPacketInformation = GetIPPacketInformation(&messageHeader, isIPv4, isIPv6);
@ -581,13 +609,39 @@ namespace System.Net.Sockets
{
Interop.Error errno;
int received;
if (buffers != null)
{
// Receive into a set of buffers
Debug.Assert(buffer == null);
received = Receive(socket, flags, buffers, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
}
else if (count == 0)
{
// Special case a receive of 0 bytes into a single buffer. A common pattern is to ReceiveAsync 0 bytes in order
// to be asynchronously notified when data is available, without needing to dedicate a buffer. Some platforms (e.g. macOS),
// however, special-case a receive of 0 to always succeed immediately even if data isn't available. As such, we treat 0
// specially, checking whether any bytes are available rather than doing an actual receive.
receivedFlags = SocketFlags.None;
received = -1;
int available = 0;
errno = Interop.Sys.GetBytesAvailable(socket, &available);
if (errno == Interop.Error.SUCCESS)
{
if (available > 0)
{
bytesReceived = 0;
errorCode = SocketError.Success;
return true;
}
errno = Interop.Error.EAGAIN; // simulate a receive with no data available
}
}
else
{
// Receive > 0 bytes into a single buffer
received = Receive(socket, flags, buffer, offset, count, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
}
@ -732,6 +786,7 @@ namespace System.Net.Sockets
try
{
sent = SendFile(socket, handle, ref offset, ref count, out errno);
bytesSent += sent;
}
catch (ObjectDisposedException)
{
@ -740,7 +795,7 @@ namespace System.Net.Sockets
return true;
}
if (sent == -1)
if (errno != Interop.Error.SUCCESS)
{
if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
{
@ -752,8 +807,6 @@ namespace System.Net.Sockets
return false;
}
bytesSent += sent;
if (sent == 0 || count == 0)
{
errorCode = SocketError.Success;
@ -979,7 +1032,7 @@ namespace System.Net.Sockets
public static SocketError WindowsIoctl(SafeCloseSocket handle, int ioControlCode, byte[] optionInValue, byte[] optionOutValue, out int optionLength)
{
throw new PlatformNotSupportedException();
throw new PlatformNotSupportedException(SR.PlatformNotSupported_IOControl);
}
private static SocketError GetErrorAndTrackSetting(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, Interop.Error err)
@ -1120,7 +1173,7 @@ namespace System.Net.Sockets
public static void SetIPProtectionLevel(Socket socket, SocketOptionLevel optionLevel, int protectionLevel)
{
throw new PlatformNotSupportedException();
throw new PlatformNotSupportedException(SR.PlatformNotSupported_IPProtectionLevel);
}
public static unsafe SocketError GetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, out int optionValue)

View File

@ -140,7 +140,6 @@ namespace System.Net.Sockets
WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
}
// This may throw ObjectDisposedException.
unsafe
{
SocketError errorCode = Interop.Winsock.WSASend(
@ -269,7 +268,6 @@ namespace System.Net.Sockets
WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
}
// This can throw ObjectDisposedException.
unsafe
{
SocketError errorCode = Interop.Winsock.WSARecv(
@ -828,16 +826,16 @@ namespace System.Net.Sockets
asyncResult.SetUnmanagedStructures(buffer, offset, count, null);
try
{
// This can throw ObjectDisposedException.
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSASend(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref asyncResult._singleBuffer,
1, // There is only ever 1 buffer being sent.
out bytesTransferred,
socketFlags,
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}
@ -854,16 +852,16 @@ namespace System.Net.Sockets
asyncResult.SetUnmanagedStructures(buffers);
try
{
// This can throw ObjectDisposedException.
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSASend(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
asyncResult._wsaBuffers,
asyncResult._wsaBuffers.Length,
out bytesTransferred,
socketFlags,
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}
@ -937,7 +935,7 @@ namespace System.Net.Sockets
{
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSASendTo(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref asyncResult._singleBuffer,
1, // There is only ever 1 buffer being sent.
out bytesTransferred,
@ -946,6 +944,7 @@ namespace System.Net.Sockets
asyncResult.SocketAddress.Size,
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}
@ -962,16 +961,16 @@ namespace System.Net.Sockets
asyncResult.SetUnmanagedStructures(buffer, offset, count, null);
try
{
// This can throw ObjectDisposedException.
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSARecv(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref asyncResult._singleBuffer,
1,
out bytesTransferred,
ref socketFlags,
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}
@ -988,16 +987,16 @@ namespace System.Net.Sockets
asyncResult.SetUnmanagedStructures(buffers);
try
{
// This can throw ObjectDisposedException.
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSARecv(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
asyncResult._wsaBuffers,
asyncResult._wsaBuffers.Length,
out bytesTransferred,
ref socketFlags,
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}
@ -1016,7 +1015,7 @@ namespace System.Net.Sockets
{
int bytesTransferred;
SocketError errorCode = Interop.Winsock.WSARecvFrom(
handle,
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
ref asyncResult._singleBuffer,
1,
out bytesTransferred,
@ -1025,6 +1024,7 @@ namespace System.Net.Sockets
asyncResult.GetSocketAddressSizePtr(),
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
IntPtr.Zero);
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
}

View File

@ -0,0 +1,250 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading.Tasks;
namespace System.Net.Sockets
{
public static class SocketTaskExtensions
{
public static Task<Socket> AcceptAsync(this Socket socket)
{
return Task<Socket>.Factory.FromAsync(
(callback, state) => ((Socket)state).BeginAccept(callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
state: socket);
}
public static Task<Socket> AcceptAsync(this Socket socket, Socket acceptSocket)
{
const int ReceiveSize = 0;
return Task<Socket>.Factory.FromAsync(
(socketForAccept, receiveSize, callback, state) => ((Socket)state).BeginAccept(socketForAccept, receiveSize, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
acceptSocket,
ReceiveSize,
state: socket);
}
public static Task ConnectAsync(this Socket socket, EndPoint remoteEndPoint)
{
return Task.Factory.FromAsync(
(targetEndPoint, callback, state) => ((Socket)state).BeginConnect(targetEndPoint, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
remoteEndPoint,
state: socket);
}
public static Task ConnectAsync(this Socket socket, IPAddress address, int port)
{
return Task.Factory.FromAsync(
(targetAddress, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddress, targetPort, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
address,
port,
state: socket);
}
public static Task ConnectAsync(this Socket socket, IPAddress[] addresses, int port)
{
return Task.Factory.FromAsync(
(targetAddresses, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddresses, targetPort, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
addresses,
port,
state: socket);
}
public static Task ConnectAsync(this Socket socket, string host, int port)
{
return Task.Factory.FromAsync(
(targetHost, targetPort, callback, state) => ((Socket)state).BeginConnect(targetHost, targetPort, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
host,
port,
state: socket);
}
public static Task<int> ReceiveAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
{
return Task<int>.Factory.FromAsync(
(targetBuffer, flags, callback, state) => ((Socket)state).BeginReceive(
targetBuffer.Array,
targetBuffer.Offset,
targetBuffer.Count,
flags,
callback,
state),
asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
buffer,
socketFlags,
state: socket);
}
public static Task<int> ReceiveAsync(
this Socket socket,
IList<ArraySegment<byte>> buffers,
SocketFlags socketFlags)
{
return Task<int>.Factory.FromAsync(
(targetBuffers, flags, callback, state) => ((Socket)state).BeginReceive(targetBuffers, flags, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
buffers,
socketFlags,
state: socket);
}
public static Task<SocketReceiveFromResult> ReceiveFromAsync(
this Socket socket,
ArraySegment<byte> buffer,
SocketFlags socketFlags,
EndPoint remoteEndPoint)
{
object[] packedArguments = new object[] { socket, remoteEndPoint };
return Task<SocketReceiveFromResult>.Factory.FromAsync(
(targetBuffer, flags, callback, state) =>
{
var arguments = (object[])state;
var s = (Socket)arguments[0];
var e = (EndPoint)arguments[1];
IAsyncResult result = s.BeginReceiveFrom(
targetBuffer.Array,
targetBuffer.Offset,
targetBuffer.Count,
flags,
ref e,
callback,
state);
arguments[1] = e;
return result;
},
asyncResult =>
{
var arguments = (object[])asyncResult.AsyncState;
var s = (Socket)arguments[0];
var e = (EndPoint)arguments[1];
int bytesReceived = s.EndReceiveFrom(asyncResult, ref e);
return new SocketReceiveFromResult()
{
ReceivedBytes = bytesReceived,
RemoteEndPoint = e
};
},
buffer,
socketFlags,
state: packedArguments);
}
public static Task<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(
this Socket socket,
ArraySegment<byte> buffer,
SocketFlags socketFlags,
EndPoint remoteEndPoint)
{
object[] packedArguments = new object[] { socket, socketFlags, remoteEndPoint };
return Task<SocketReceiveMessageFromResult>.Factory.FromAsync(
(targetBuffer, callback, state) =>
{
var arguments = (object[])state;
var s = (Socket)arguments[0];
var f = (SocketFlags)arguments[1];
var e = (EndPoint)arguments[2];
IAsyncResult result = s.BeginReceiveMessageFrom(
targetBuffer.Array,
targetBuffer.Offset,
targetBuffer.Count,
f,
ref e,
callback,
state);
arguments[2] = e;
return result;
},
asyncResult =>
{
var arguments = (object[])asyncResult.AsyncState;
var s = (Socket)arguments[0];
var f = (SocketFlags)arguments[1];
var e = (EndPoint)arguments[2];
IPPacketInformation ipPacket;
int bytesReceived = s.EndReceiveMessageFrom(
asyncResult,
ref f,
ref e,
out ipPacket);
return new SocketReceiveMessageFromResult()
{
PacketInformation = ipPacket,
ReceivedBytes = bytesReceived,
RemoteEndPoint = e,
SocketFlags = f
};
},
buffer,
state: packedArguments);
}
public static Task<int> SendAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
{
return Task<int>.Factory.FromAsync(
(targetBuffer, flags, callback, state) => ((Socket)state).BeginSend(
targetBuffer.Array,
targetBuffer.Offset,
targetBuffer.Count,
flags,
callback,
state),
asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
buffer,
socketFlags,
state: socket);
}
public static Task<int> SendAsync(
this Socket socket,
IList<ArraySegment<byte>> buffers,
SocketFlags socketFlags)
{
return Task<int>.Factory.FromAsync(
(targetBuffers, flags, callback, state) => ((Socket)state).BeginSend(targetBuffers, flags, callback, state),
asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
buffers,
socketFlags,
state: socket);
}
public static Task<int> SendToAsync(
this Socket socket,
ArraySegment<byte> buffer,
SocketFlags socketFlags,
EndPoint remoteEndPoint)
{
return Task<int>.Factory.FromAsync(
(targetBuffer, flags, endPoint, callback, state) => ((Socket)state).BeginSendTo(
targetBuffer.Array,
targetBuffer.Offset,
targetBuffer.Count,
flags,
endPoint,
callback,
state),
asyncResult => ((Socket)asyncResult.AsyncState).EndSendTo(asyncResult),
buffer,
socketFlags,
remoteEndPoint,
state: socket);
}
}
}

View File

@ -5,7 +5,7 @@
namespace System.Net
{
// Defines the transport type allowed for the socket.
public enum TransportType
internal enum TransportType
{
// Udp connections are allowed.
Udp = 1,

View File

@ -667,5 +667,326 @@ namespace System.Net.Sockets
// IPv6 Changes: Use the AddressFamily of this class rather than hardcode.
_clientSocket = new Socket(_family, SocketType.Dgram, ProtocolType.Udp);
}
public UdpClient(string hostname, int port)
{
if (hostname == null)
{
throw new ArgumentNullException(nameof(hostname));
}
if (!TcpValidationHelpers.ValidatePortNumber(port))
{
throw new ArgumentOutOfRangeException(nameof(port));
}
// NOTE: Need to create different kinds of sockets based on the addresses
// returned from DNS. As a result, we defer the creation of the
// socket until the Connect method.
Connect(hostname, port);
}
public void Close()
{
Dispose(true);
}
public void Connect(string hostname, int port)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (hostname == null)
{
throw new ArgumentNullException(nameof(hostname));
}
if (!TcpValidationHelpers.ValidatePortNumber(port))
{
throw new ArgumentOutOfRangeException(nameof(port));
}
// We must now look for addresses that use a compatible address family to the client socket. However, in the
// case of the <hostname,port> constructor we will have deferred creating the socket and will do that here
// instead.
IPAddress[] addresses = Dns.GetHostAddresses(hostname);
Exception lastex = null;
Socket ipv6Socket = null;
Socket ipv4Socket = null;
try
{
if (_clientSocket == null)
{
if (Socket.OSSupportsIPv4)
{
ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
}
if (Socket.OSSupportsIPv6)
{
ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
}
}
foreach (IPAddress address in addresses)
{
try
{
if (_clientSocket == null)
{
// We came via the <hostname,port> constructor. Set the
// address family appropriately, create the socket and
// try to connect.
if (address.AddressFamily == AddressFamily.InterNetwork && ipv4Socket != null)
{
ipv4Socket.Connect(address, port);
_clientSocket = ipv4Socket;
if (ipv6Socket != null)
{
ipv6Socket.Close();
}
}
else if (ipv6Socket != null)
{
ipv6Socket.Connect(address, port);
_clientSocket = ipv6Socket;
if (ipv4Socket != null)
{
ipv4Socket.Close();
}
}
_family = address.AddressFamily;
_active = true;
break;
}
else if (address.AddressFamily == _family)
{
// Only use addresses with a matching family
Connect(new IPEndPoint(address, port));
_active = true;
break;
}
}
catch (Exception ex)
{
if (ExceptionCheck.IsFatal(ex))
{
throw;
}
lastex = ex;
}
}
}
catch (Exception ex)
{
if (ExceptionCheck.IsFatal(ex))
{
throw;
}
lastex = ex;
}
finally
{
//cleanup temp sockets if failed
//main socket gets closed when tcpclient gets closed
//did we connect?
if (!_active)
{
if (ipv6Socket != null)
{
ipv6Socket.Close();
}
if (ipv4Socket != null)
{
ipv4Socket.Close();
}
// The connect failed - rethrow the last error we had
if (lastex != null)
{
throw lastex;
}
else
{
throw new SocketException((int)SocketError.NotConnected);
}
}
}
}
public void Connect(IPAddress addr, int port)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (addr == null)
{
throw new ArgumentNullException(nameof(addr));
}
if (!TcpValidationHelpers.ValidatePortNumber(port))
{
throw new ArgumentOutOfRangeException(nameof(port));
}
IPEndPoint endPoint = new IPEndPoint(addr, port);
Connect(endPoint);
}
public void Connect(IPEndPoint endPoint)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (endPoint == null)
{
throw new ArgumentNullException(nameof(endPoint));
}
CheckForBroadcast(endPoint.Address);
Client.Connect(endPoint);
_active = true;
}
public byte[] Receive(ref IPEndPoint remoteEP)
{
//
// parameter validation
//
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
// this is a fix due to the nature of the ReceiveFrom() call and the
// ref parameter convention, we need to cast an IPEndPoint to it's base
// class EndPoint and cast it back down to IPEndPoint. ugly but it works.
//
EndPoint tempRemoteEP;
if (_family == AddressFamily.InterNetwork)
{
tempRemoteEP = IPEndPointStatics.Any;
}
else
{
tempRemoteEP = IPEndPointStatics.IPv6Any;
}
int received = Client.ReceiveFrom(_buffer, MaxUDPSize, 0, ref tempRemoteEP);
remoteEP = (IPEndPoint)tempRemoteEP;
// because we don't return the actual length, we need to ensure the returned buffer
// has the appropriate length.
if (received < MaxUDPSize)
{
byte[] newBuffer = new byte[received];
Buffer.BlockCopy(_buffer, 0, newBuffer, 0, received);
return newBuffer;
}
return _buffer;
}
// Sends a UDP datagram to the host at the remote end point.
public int Send(byte[] dgram, int bytes, IPEndPoint endPoint)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (dgram == null)
{
throw new ArgumentNullException(nameof(dgram));
}
if (_active && endPoint != null)
{
// Do not allow sending packets to arbitrary host when connected
throw new InvalidOperationException(SR.net_udpconnected);
}
if (endPoint == null)
{
return Client.Send(dgram, 0, bytes, SocketFlags.None);
}
CheckForBroadcast(endPoint.Address);
return Client.SendTo(dgram, 0, bytes, SocketFlags.None, endPoint);
}
// Sends a UDP datagram to the specified port on the specified remote host.
public int Send(byte[] dgram, int bytes, string hostname, int port)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (dgram == null)
{
throw new ArgumentNullException(nameof(dgram));
}
if (_active && ((hostname != null) || (port != 0)))
{
// Do not allow sending packets to arbitrary host when connected
throw new InvalidOperationException(SR.net_udpconnected);
}
if (hostname == null || port == 0)
{
return Client.Send(dgram, 0, bytes, SocketFlags.None);
}
IPAddress[] addresses = Dns.GetHostAddresses(hostname);
int i = 0;
for (; i < addresses.Length && addresses[i].AddressFamily != _family; i++)
{
; // just count the addresses
}
if (addresses.Length == 0 || i == addresses.Length)
{
throw new ArgumentException(SR.net_invalidAddressList, nameof(hostname));
}
CheckForBroadcast(addresses[i]);
IPEndPoint ipEndPoint = new IPEndPoint(addresses[i], port);
return Client.SendTo(dgram, 0, bytes, SocketFlags.None, ipEndPoint);
}
// Sends a UDP datagram to a remote host.
public int Send(byte[] dgram, int bytes)
{
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (dgram == null)
{
throw new ArgumentNullException(nameof(dgram));
}
if (!_active)
{
// only allowed on connected socket
throw new InvalidOperationException(SR.net_notconnected);
}
return Client.Send(dgram, 0, bytes, SocketFlags.None);
}
}
}

Some files were not shown because too many files have changed in this diff Show More