@@ -1380,6 +1380,67 @@ public int SendTo(byte[] buffer, EndPoint remoteEP)
13801380 return SendTo ( buffer , 0 , buffer != null ? buffer . Length : 0 , SocketFlags . None , remoteEP ) ;
13811381 }
13821382
1383+ /// <summary>
1384+ /// Sends data to the specified endpoint.
1385+ /// </summary>
1386+ /// <param name="buffer">A span of bytes that contains the data to be sent.</param>
1387+ /// <param name="remoteEP">The <see cref="EndPoint"/> that represents the destination for the data.</param>
1388+ /// <returns>The number of bytes sent.</returns>
1389+ /// <exception cref="ArgumentNullException"><c>remoteEP</c> is <see langword="null" />.</exception>
1390+ /// <exception cref="SocketException">An error occurred when attempting to access the socket.</exception>
1391+ /// <exception cref="ObjectDisposedException">The <see cref="Socket"/> has been closed.</exception>
1392+ public int SendTo ( ReadOnlySpan < byte > buffer , EndPoint remoteEP )
1393+ {
1394+ return SendTo ( buffer , SocketFlags . None , remoteEP ) ;
1395+ }
1396+
1397+ /// <summary>
1398+ /// Sends data to a specific endpoint using the specified <see cref="SocketFlags"/>.
1399+ /// </summary>
1400+ /// <param name="buffer">A span of bytes that contains the data to be sent.</param>
1401+ /// <param name="socketFlags">A bitwise combination of the <see cref="SocketFlags"/> values.</param>
1402+ /// <param name="remoteEP">The <see cref="EndPoint"/> that represents the destination for the data.</param>
1403+ /// <returns>The number of bytes sent.</returns>
1404+ /// <exception cref="ArgumentNullException"><c>remoteEP</c> is <see langword="null" />.</exception>
1405+ /// <exception cref="SocketException">An error occurred when attempting to access the socket.</exception>
1406+ /// <exception cref="ObjectDisposedException">The <see cref="Socket"/> has been closed.</exception>
1407+ public int SendTo ( ReadOnlySpan < byte > buffer , SocketFlags socketFlags , EndPoint remoteEP )
1408+ {
1409+ ThrowIfDisposed ( ) ;
1410+ if ( remoteEP == null )
1411+ {
1412+ throw new ArgumentNullException ( nameof ( remoteEP ) ) ;
1413+ }
1414+
1415+ ValidateBlockingMode ( ) ;
1416+
1417+ Internals . SocketAddress socketAddress = Serialize ( ref remoteEP ) ;
1418+
1419+ int bytesTransferred ;
1420+ SocketError errorCode = SocketPal . SendTo ( _handle , buffer , socketFlags , socketAddress . Buffer , socketAddress . Size , out bytesTransferred ) ;
1421+
1422+ // Throw an appropriate SocketException if the native call fails.
1423+ if ( errorCode != SocketError . Success )
1424+ {
1425+ UpdateSendSocketErrorForDisposed ( ref errorCode ) ;
1426+
1427+ UpdateStatusAfterSocketErrorAndThrowException ( errorCode ) ;
1428+ }
1429+ else if ( SocketsTelemetry . Log . IsEnabled ( ) )
1430+ {
1431+ SocketsTelemetry . Log . BytesSent ( bytesTransferred ) ;
1432+ if ( SocketType == SocketType . Dgram ) SocketsTelemetry . Log . DatagramSent ( ) ;
1433+ }
1434+
1435+ if ( _rightEndPoint == null )
1436+ {
1437+ // Save a copy of the EndPoint so we can use it for Create().
1438+ _rightEndPoint = remoteEP ;
1439+ }
1440+
1441+ return bytesTransferred ;
1442+ }
1443+
13831444 // Receives data from a connected socket.
13841445 public int Receive ( byte [ ] buffer , int size , SocketFlags socketFlags )
13851446 {
@@ -1764,6 +1825,93 @@ public int ReceiveFrom(byte[] buffer, ref EndPoint remoteEP)
17641825 return ReceiveFrom ( buffer , 0 , buffer != null ? buffer . Length : 0 , SocketFlags . None , ref remoteEP ) ;
17651826 }
17661827
1828+ /// <summary>
1829+ /// Receives a datagram into the data buffer and stores the endpoint.
1830+ /// </summary>
1831+ /// <param name="buffer">A span of bytes that is the storage location for received data.</param>
1832+ /// <param name="remoteEP">An <see cref="EndPoint"/>, passed by reference, that represents the remote server.</param>
1833+ /// <returns>The number of bytes received.</returns>
1834+ /// <exception cref="ArgumentNullException"><c>remoteEP</c> is <see langword="null" />.</exception>
1835+ /// <exception cref="SocketException">An error occurred when attempting to access the socket.</exception>
1836+ /// <exception cref="ObjectDisposedException">The <see cref="Socket"/> has been closed.</exception>
1837+ public int ReceiveFrom ( Span < byte > buffer , ref EndPoint remoteEP )
1838+ {
1839+ return ReceiveFrom ( buffer , SocketFlags . None , ref remoteEP ) ;
1840+ }
1841+
1842+ /// <summary>
1843+ /// Receives a datagram into the data buffer, using the specified <see cref="SocketFlags"/>, and stores the endpoint.
1844+ /// </summary>
1845+ /// <param name="buffer">A span of bytes that is the storage location for received data.</param>
1846+ /// <param name="socketFlags">A bitwise combination of the <see cref="SocketFlags"/> values.</param>
1847+ /// <param name="remoteEP">An <see cref="EndPoint"/>, passed by reference, that represents the remote server.</param>
1848+ /// <returns>The number of bytes received.</returns>
1849+ /// <exception cref="ArgumentNullException"><c>remoteEP</c> is <see langword="null" />.</exception>
1850+ /// <exception cref="SocketException">An error occurred when attempting to access the socket.</exception>
1851+ /// <exception cref="ObjectDisposedException">The <see cref="Socket"/> has been closed.</exception>
1852+ public int ReceiveFrom ( Span < byte > buffer , SocketFlags socketFlags , ref EndPoint remoteEP )
1853+ {
1854+ ThrowIfDisposed ( ) ;
1855+ ValidateReceiveFromEndpointAndState ( remoteEP , nameof ( remoteEP ) ) ;
1856+
1857+ SocketPal . CheckDualModeReceiveSupport ( this ) ;
1858+
1859+ ValidateBlockingMode ( ) ;
1860+
1861+ // We don't do a CAS demand here because the contents of remoteEP aren't used by
1862+ // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
1863+ // with the right address family.
1864+ EndPoint endPointSnapshot = remoteEP ;
1865+ Internals . SocketAddress socketAddress = Serialize ( ref endPointSnapshot ) ;
1866+ Internals . SocketAddress socketAddressOriginal = IPEndPointExtensions . Serialize ( endPointSnapshot ) ;
1867+
1868+ int bytesTransferred ;
1869+ SocketError errorCode = SocketPal . ReceiveFrom ( _handle , buffer , socketFlags , socketAddress . Buffer , ref socketAddress . InternalSize , out bytesTransferred ) ;
1870+
1871+ UpdateReceiveSocketErrorForDisposed ( ref errorCode , bytesTransferred ) ;
1872+ // If the native call fails we'll throw a SocketException.
1873+ SocketException ? socketException = null ;
1874+ if ( errorCode != SocketError . Success )
1875+ {
1876+ socketException = new SocketException ( ( int ) errorCode ) ;
1877+ UpdateStatusAfterSocketError ( socketException ) ;
1878+ if ( NetEventSource . Log . IsEnabled ( ) ) NetEventSource . Error ( this , socketException ) ;
1879+
1880+ if ( socketException . SocketErrorCode != SocketError . MessageSize )
1881+ {
1882+ throw socketException ;
1883+ }
1884+ }
1885+ else if ( SocketsTelemetry . Log . IsEnabled ( ) )
1886+ {
1887+ SocketsTelemetry . Log . BytesReceived ( bytesTransferred ) ;
1888+ if ( SocketType == SocketType . Dgram ) SocketsTelemetry . Log . DatagramReceived ( ) ;
1889+ }
1890+
1891+ if ( ! socketAddressOriginal . Equals ( socketAddress ) )
1892+ {
1893+ try
1894+ {
1895+ remoteEP = endPointSnapshot . Create ( socketAddress ) ;
1896+ }
1897+ catch
1898+ {
1899+ }
1900+ if ( _rightEndPoint == null )
1901+ {
1902+ // Save a copy of the EndPoint so we can use it for Create().
1903+ _rightEndPoint = endPointSnapshot ;
1904+ }
1905+ }
1906+
1907+ if ( socketException != null )
1908+ {
1909+ throw socketException ;
1910+ }
1911+
1912+ return bytesTransferred ;
1913+ }
1914+
17671915 public int IOControl ( int ioControlCode , byte [ ] ? optionInValue , byte [ ] ? optionOutValue )
17681916 {
17691917 ThrowIfDisposed ( ) ;
0 commit comments