The Labs \ Source Viewer \ SSCLI \ System.Net.Sockets \ UdpClient

  1. //------------------------------------------------------------------------------
  2. // <copyright file="UDPClient.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net.Sockets
  16. {
  17.    
  18.     using System.Security.Permissions;
  19.    
  20.     /// <devdoc>
  21.     /// <para>
  22.     /// The <see cref='System.Net.Sockets.UdpClient'/> class provides access to UDP services at a
  23.     /// higher abstraction level than the <see cref='System.Net.Sockets.Socket'/> class. <see cref='System.Net.Sockets.UdpClient'/>
  24.     /// is used to connect to a remote host and to receive connections from a remote
  25.     /// Client.
  26.     /// </para>
  27.     /// </devdoc>
  28.     public class UdpClient : IDisposable
  29.     {
  30.        
  31.         private const int MaxUDPSize = 65536;
  32.         private Socket m_ClientSocket;
  33.         private bool m_Active;
  34.         private byte[] m_Buffer = new byte[MaxUDPSize];
  35.         /// <devdoc>
  36.         /// <para>
  37.         /// Address family for the client, defaults to IPv4.
  38.         /// </para>
  39.         /// </devdoc>
  40.         private AddressFamily m_Family = AddressFamily.InterNetwork;
  41.        
  42.         // bind to arbitrary IP+Port
  43.         /// <devdoc>
  44.         /// <para>
  45.         /// Initializes a new instance of the <see cref='System.Net.Sockets.UdpClient'/>class.
  46.         /// </para>
  47.         /// </devdoc>
  48.         public UdpClient() : this(AddressFamily.InterNetwork)
  49.         {
  50.         }
  51.        
  52.         /// <devdoc>
  53.         /// <para>
  54.         /// Initializes a new instance of the <see cref='System.Net.Sockets.UdpClient'/>class.
  55.         /// </para>
  56.         /// </devdoc>
  57.        
  58.         public UdpClient(AddressFamily family)
  59.         {
  60.             //
  61.             // Validate the address family
  62.             //
  63.             if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) {
  64.                 throw new ArgumentException(SR.GetString(SR.net_protocol_invalid_family, "UDP"), "family");
  65.             }
  66.            
  67.             m_Family = family;
  68.            
  69.             createClientSocket();
  70.         }
  71.        
  72.         // bind specific port, arbitrary IP
  73.         /// <devdoc>
  74.         /// <para>
  75.         /// Creates a new instance of the UdpClient class that communicates on the
  76.         /// specified port number.
  77.         /// </para>
  78.         /// </devdoc>
  79.         public UdpClient(int port) : this(port, AddressFamily.InterNetwork)
  80.         {
  81.         }
  82.        
  83.         /// <devdoc>
  84.         /// <para>
  85.         /// Creates a new instance of the UdpClient class that communicates on the
  86.         /// specified port number.
  87.         /// </para>
  88.         /// </devdoc>
  89.         public UdpClient(int port, AddressFamily family)
  90.         {
  91.             //
  92.             // parameter validation
  93.             //
  94.             if (!ValidationHelper.ValidateTcpPort(port)) {
  95.                 throw new ArgumentOutOfRangeException("port");
  96.             }
  97.             //
  98.             // Validate the address family
  99.             //
  100.             if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) {
  101.                 throw new ArgumentException(SR.GetString(SR.net_protocol_invalid_family), "family");
  102.             }
  103.            
  104.             IPEndPoint localEP;
  105.             m_Family = family;
  106.            
  107.             if (m_Family == AddressFamily.InterNetwork) {
  108.                 localEP = new IPEndPoint(IPAddress.Any, port);
  109.             }
  110.             else {
  111.                 localEP = new IPEndPoint(IPAddress.IPv6Any, port);
  112.             }
  113.            
  114.             createClientSocket();
  115.            
  116.             Client.Bind(localEP);
  117.         }
  118.        
  119.         // bind to given local endpoint
  120.         /// <devdoc>
  121.         /// <para>
  122.         /// Creates a new instance of the UdpClient class that communicates on the
  123.         /// specified end point.
  124.         /// </para>
  125.         /// </devdoc>
  126.         public UdpClient(IPEndPoint localEP)
  127.         {
  128.             //
  129.             // parameter validation
  130.             //
  131.             if (localEP == null) {
  132.                 throw new ArgumentNullException("localEP");
  133.             }
  134.             //
  135.             // IPv6 Changes: Set the AddressFamily of this object before
  136.             // creating the client socket.
  137.             //
  138.             m_Family = localEP.AddressFamily;
  139.            
  140.             createClientSocket();
  141.            
  142.             Client.Bind(localEP);
  143.         }
  144.        
  145.         // bind and connect
  146.         /// <devdoc>
  147.         /// <para>
  148.         /// Creates a new instance of the <see cref='System.Net.Sockets.UdpClient'/> class and connects to the
  149.         /// specified remote host on the specified port.
  150.         /// </para>
  151.         /// </devdoc>
  152.         public UdpClient(string hostname, int port)
  153.         {
  154.             //
  155.             // parameter validation
  156.             //
  157.             if (hostname == null) {
  158.                 throw new ArgumentNullException("hostname");
  159.             }
  160.             if (!ValidationHelper.ValidateTcpPort(port)) {
  161.                 throw new ArgumentOutOfRangeException("port");
  162.             }
  163.             //
  164.             // NOTE: Need to create different kinds of sockets based on the addresses
  165.             // returned from DNS. As a result, we defer the creation of the
  166.             // socket until the Connect method.
  167.             //
  168.             //createClientSocket();
  169.             Connect(hostname, port);
  170.         }
  171.        
  172.         /// <devdoc>
  173.         /// <para>
  174.         /// Used by the class to provide the underlying network socket.
  175.         /// </para>
  176.         /// </devdoc>
  177.         public Socket Client {
  178.             get { return m_ClientSocket; }
  179.             set { m_ClientSocket = value; }
  180.         }
  181.        
  182.         /// <devdoc>
  183.         /// <para>
  184.         /// Used by the class to indicate that a connection to a remote host has been
  185.         /// made.
  186.         /// </para>
  187.         /// </devdoc>
  188.         protected bool Active {
  189.             get { return m_Active; }
  190.             set { m_Active = value; }
  191.         }
  192.        
  193.         public int Available {
  194.             get { return m_ClientSocket.Available; }
  195.         }
  196.        
  197.         public short Ttl {
  198.             get { return m_ClientSocket.Ttl; }
  199.             set { m_ClientSocket.Ttl = value; }
  200.         }
  201.         //new
  202.        
  203.         public bool DontFragment {
  204.             get { return m_ClientSocket.DontFragment; }
  205.             set { m_ClientSocket.DontFragment = value; }
  206.         }
  207.         //new
  208.        
  209.         public bool MulticastLoopback {
  210.             get { return m_ClientSocket.MulticastLoopback; }
  211.             set { m_ClientSocket.MulticastLoopback = value; }
  212.         }
  213.         //new
  214.        
  215.        
  216.         public bool EnableBroadcast {
  217.             get { return m_ClientSocket.EnableBroadcast; }
  218.             set { m_ClientSocket.EnableBroadcast = value; }
  219.         }
  220.         //new
  221.        
  222.         public bool ExclusiveAddressUse {
  223.             get { return m_ClientSocket.ExclusiveAddressUse; }
  224.             set { m_ClientSocket.ExclusiveAddressUse = value; }
  225.         }
  226.         //new
  227.        
  228.         public void Close()
  229.         {
  230.             Dispose(true);
  231.         }
  232.        
  233.         private bool m_CleanedUp = false;
  234.         private void FreeResources()
  235.         {
  236.             //
  237.             // only resource we need to free is the network stream, since this
  238.             // is based on the client socket, closing the stream will cause us
  239.             // to flush the data to the network, close the stream and (in the
  240.             // NetoworkStream code) close the socket as well.
  241.             //
  242.             if (m_CleanedUp) {
  243.                 return;
  244.             }
  245.            
  246.             Socket chkClientSocket = Client;
  247.             if (chkClientSocket != null) {
  248.                 //
  249.                 // if the NetworkStream wasn't retrieved, the Socket might
  250.                 // still be there and needs to be closed to release the effect
  251.                 // of the Bind() call and free the bound IPEndPoint.
  252.                 //
  253.                 chkClientSocket.InternalShutdown(SocketShutdown.Both);
  254.                 chkClientSocket.Close();
  255.                 Client = null;
  256.             }
  257.             m_CleanedUp = true;
  258.         }
  259.        
  260.         /// <internalonly/>
  261.         void IDisposable.Dispose()
  262.         {
  263.             Dispose(true);
  264.         }
  265.        
  266.         protected virtual void Dispose(bool disposing)
  267.         {
  268.             if (disposing) {
  269.                 GlobalLog.Print("UdpClient::Dispose()");
  270.                 FreeResources();
  271.                 GC.SuppressFinalize(this);
  272.             }
  273.         }
  274.        
  275.         /// <devdoc>
  276.         /// <para>
  277.         /// Establishes a connection to the specified port on the
  278.         /// specified host.
  279.         /// </para>
  280.         /// </devdoc>
  281.         public void Connect(string hostname, int port)
  282.         {
  283.             //
  284.             // parameter validation
  285.             //
  286.             if (m_CleanedUp) {
  287.                 throw new ObjectDisposedException(this.GetType().FullName);
  288.             }
  289.             if (!ValidationHelper.ValidateTcpPort(port)) {
  290.                 throw new ArgumentOutOfRangeException("port");
  291.             }
  292.            
  293.             //
  294.             // IPv6 Changes: instead of just using the first address in the list,
  295.             // we must now look for addresses that use a compatible
  296.             // address family to the client socket.
  297.             // However, in the case of the <hostname,port> constructor
  298.             // we will have deferred creating the socket and will
  299.             // do that here instead.
  300.             // In addition, the redundant CheckForBroadcast call was
  301.             // removed here since it is called from Connect().
  302.             //
  303.             IPAddress[] addresses = Dns.GetHostAddresses(hostname);
  304.            
  305.             foreach (IPAddress address in addresses) {
  306.                 if (m_ClientSocket == null) {
  307.                     //
  308.                     // We came via the <hostname,port> constructor. Set the
  309.                     // address family appropriately, create the socket and
  310.                     // try to connect.
  311.                     //
  312.                     m_Family = address.AddressFamily;
  313.                    
  314.                     createClientSocket();
  315.                    
  316.                     try {
  317.                         //
  318.                         // Attempt to connect to the host
  319.                         //
  320.                         Connect(new IPEndPoint(address, port));
  321.                        
  322.                         break;
  323.                     }
  324.                     catch (SocketException) {
  325.                         //
  326.                         // Destroy the client socket here for retry with
  327.                         // the next address.
  328.                         //
  329.                         try {
  330.                             m_ClientSocket.InternalShutdown(SocketShutdown.Both);
  331.                         }
  332.                         finally {
  333.                             m_ClientSocket.Close();
  334.                         }
  335.                     }
  336.                 }
  337.                 else if (address.AddressFamily == m_Family) {
  338.                     //
  339.                     // Only use addresses with a matching family
  340.                     //
  341.                     try {
  342.                         //
  343.                         // Attempt to connect to the host
  344.                         //
  345.                         Connect(new IPEndPoint(address, port));
  346.                        
  347.                         break;
  348.                     }
  349.                     catch (SocketException) {
  350.                         //
  351.                         // Intentionally empty - all set to retry the next address
  352.                         //
  353.                     }
  354.                 }
  355.             }
  356.             //
  357.             // m_Active tells us whether we managed to connect
  358.             //
  359.             if (!m_Active) {
  360.                 throw new SocketException(SocketError.NotConnected);
  361.             }
  362.         }
  363.        
  364.         /// <devdoc>
  365.         /// <para>
  366.         /// Establishes a connection with the host at the specified address on the
  367.         /// specified port.
  368.         /// </para>
  369.         /// </devdoc>
  370.         public void Connect(IPAddress addr, int port)
  371.         {
  372.             //
  373.             // parameter validation
  374.             //
  375.             if (m_CleanedUp) {
  376.                 throw new ObjectDisposedException(this.GetType().FullName);
  377.             }
  378.             if (addr == null) {
  379.                 throw new ArgumentNullException("addr");
  380.             }
  381.             if (!ValidationHelper.ValidateTcpPort(port)) {
  382.                 throw new ArgumentOutOfRangeException("port");
  383.             }
  384.            
  385.             //
  386.             // IPv6 Changes: Removed redundant call to CheckForBroadcast() since
  387.             // it is made in the real Connect() method.
  388.             //
  389.             IPEndPoint endPoint = new IPEndPoint(addr, port);
  390.            
  391.             Connect(endPoint);
  392.         }
  393.        
  394.         /// <devdoc>
  395.         /// <para>
  396.         /// Establishes a connection to a remote end point.
  397.         /// </para>
  398.         /// </devdoc>
  399.         public void Connect(IPEndPoint endPoint)
  400.         {
  401.             //
  402.             // parameter validation
  403.             //
  404.             if (m_CleanedUp) {
  405.                 throw new ObjectDisposedException(this.GetType().FullName);
  406.             }
  407.             if (endPoint == null) {
  408.                 throw new ArgumentNullException("endPoint");
  409.             }
  410.             //
  411.             // IPv6 Changes: Actually, no changes but we might want to check for
  412.             // compatible protocols here rather than push it down
  413.             // to WinSock.
  414.             //
  415.             CheckForBroadcast(endPoint.Address);
  416.             Client.Connect(endPoint);
  417.             m_Active = true;
  418.         }
  419.        
  420.        
  421.         private bool m_IsBroadcast;
  422.         private void CheckForBroadcast(IPAddress ipAddress)
  423.         {
  424.             //
  425.             // Here we check to see if the user is trying to use a Broadcast IP address
  426.             // we only detect IPAddress.Broadcast (which is not the only Broadcast address)
  427.             // and in that case we set SocketOptionName.Broadcast on the socket to allow its use.
  428.             // if the user really wants complete control over Broadcast addresses he needs to
  429.             // inherit from UdpClient and gain control over the Socket and do whatever is appropriate.
  430.             //
  431.             if (Client != null && !m_IsBroadcast && ipAddress.IsBroadcast) {
  432.                 //
  433.                 // we need to set the Broadcast socket option.
  434.                 // note that, once we set the option on the Socket, we never reset it.
  435.                 //
  436.                 m_IsBroadcast = true;
  437.                 Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
  438.             }
  439.         }
  440.        
  441.        
  442.        
  443.         /// <devdoc>
  444.         /// <para>
  445.         /// Sends a UDP datagram to the host at the remote end point.
  446.         /// </para>
  447.         /// </devdoc>
  448.         public int Send(byte[] dgram, int bytes, IPEndPoint endPoint)
  449.         {
  450.             //
  451.             // parameter validation
  452.             //
  453.             if (m_CleanedUp) {
  454.                 throw new ObjectDisposedException(this.GetType().FullName);
  455.             }
  456.             if (dgram == null) {
  457.                 throw new ArgumentNullException("dgram");
  458.             }
  459.             if (m_Active && endPoint != null) {
  460.                 //
  461.                 // Do not allow sending packets to arbitrary host when connected
  462.                 //
  463.                 throw new InvalidOperationException(SR.GetString(SR.net_udpconnected));
  464.             }
  465.            
  466.             if (endPoint == null) {
  467.                 return Client.Send(dgram, 0, bytes, SocketFlags.None);
  468.             }
  469.            
  470.             CheckForBroadcast(endPoint.Address);
  471.            
  472.             return Client.SendTo(dgram, 0, bytes, SocketFlags.None, endPoint);
  473.         }
  474.        
  475.        
  476.         /// <devdoc>
  477.         /// <para>
  478.         /// Sends a UDP datagram to the specified port on the specified remote host.
  479.         /// </para>
  480.         /// </devdoc>
  481.         public int Send(byte[] dgram, int bytes, string hostname, int port)
  482.         {
  483.             //
  484.             // parameter validation
  485.             //
  486.             if (m_CleanedUp) {
  487.                 throw new ObjectDisposedException(this.GetType().FullName);
  488.             }
  489.             if (dgram == null) {
  490.                 throw new ArgumentNullException("dgram");
  491.             }
  492.             if (m_Active && ((hostname != null) || (port != 0))) {
  493.                 //
  494.                 // Do not allow sending packets to arbitrary host when connected
  495.                 //
  496.                 throw new InvalidOperationException(SR.GetString(SR.net_udpconnected));
  497.             }
  498.            
  499.             if (hostname == null || port == 0) {
  500.                 return Client.Send(dgram, 0, bytes, SocketFlags.None);
  501.             }
  502.            
  503.             IPAddress[] addresses = Dns.GetHostAddresses(hostname);
  504.            
  505.             int i = 0;
  506.             for (; i < addresses.Length && addresses[i].AddressFamily != m_Family; i++)
  507.                 ;
  508.            
  509.             if (addresses.Length == 0 || i == addresses.Length) {
  510.                 throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "hostname");
  511.             }
  512.            
  513.             CheckForBroadcast(addresses[i]);
  514.             IPEndPoint ipEndPoint = new IPEndPoint(addresses[i], port);
  515.             return Client.SendTo(dgram, 0, bytes, SocketFlags.None, ipEndPoint);
  516.         }
  517.        
  518.        
  519.        
  520.        
  521.         /// <devdoc>
  522.         /// <para>
  523.         /// Sends a UDP datagram to a
  524.         /// remote host.
  525.         /// </para>
  526.         /// </devdoc>
  527.         public int Send(byte[] dgram, int bytes)
  528.         {
  529.             //
  530.             // parameter validation
  531.             //
  532.             if (m_CleanedUp) {
  533.                 throw new ObjectDisposedException(this.GetType().FullName);
  534.             }
  535.             if (dgram == null) {
  536.                 throw new ArgumentNullException("dgram");
  537.             }
  538.             if (!m_Active) {
  539.                 //
  540.                 // only allowed on connected socket
  541.                 //
  542.                 throw new InvalidOperationException(SR.GetString(SR.net_notconnected));
  543.             }
  544.            
  545.             return Client.Send(dgram, 0, bytes, SocketFlags.None);
  546.            
  547.         }
  548.        
  549.        
  550.        
  551.         [HostProtection(ExternalThreading = true)]
  552.         public IAsyncResult BeginSend(byte[] datagram, int bytes, IPEndPoint endPoint, AsyncCallback requestCallback, object state)
  553.         {
  554.             //
  555.             // parameter validation
  556.             //
  557.             if (m_CleanedUp) {
  558.                 throw new ObjectDisposedException(this.GetType().FullName);
  559.             }
  560.             if (datagram == null) {
  561.                 throw new ArgumentNullException("datagram");
  562.             }
  563.            
  564.             if (bytes > datagram.Length) {
  565.                 throw new ArgumentOutOfRangeException("bytes");
  566.             }
  567.            
  568.             if (m_Active && endPoint != null) {
  569.                 //
  570.                 // Do not allow sending packets to arbitrary host when connected
  571.                 //
  572.                 throw new InvalidOperationException(SR.GetString(SR.net_udpconnected));
  573.             }
  574.            
  575.             if (endPoint == null) {
  576.                 return Client.BeginSend(datagram, 0, bytes, SocketFlags.None, requestCallback, state);
  577.             }
  578.            
  579.             CheckForBroadcast(endPoint.Address);
  580.            
  581.             return Client.BeginSendTo(datagram, 0, bytes, SocketFlags.None, endPoint, requestCallback, state);
  582.         }
  583.        
  584.        
  585.        
  586.         [HostProtection(ExternalThreading = true)]
  587.         public IAsyncResult BeginSend(byte[] datagram, int bytes, string hostname, int port, AsyncCallback requestCallback, object state)
  588.         {
  589.            
  590.             if (m_Active && ((hostname != null) || (port != 0))) {
  591.                 // Do not allow sending packets to arbitrary host when connected
  592.                 throw new InvalidOperationException(SR.GetString(SR.net_udpconnected));
  593.             }
  594.            
  595.             IPEndPoint ipEndPoint = null;
  596.            
  597.             if (hostname != null && port != 0) {
  598.                
  599.                 IPAddress[] addresses = Dns.GetHostAddresses(hostname);
  600.                
  601.                 int i = 0;
  602.                 for (; i < addresses.Length && addresses[i].AddressFamily != m_Family; i++)
  603.                     ;
  604.                
  605.                 if (addresses.Length == 0 || i == addresses.Length) {
  606.                     throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "hostname");
  607.                 }
  608.                
  609.                 CheckForBroadcast(addresses[i]);
  610.                 ipEndPoint = new IPEndPoint(addresses[i], port);
  611.             }
  612.             return BeginSend(datagram, bytes, ipEndPoint, requestCallback, state);
  613.         }
  614.        
  615.        
  616.        
  617.         [HostProtection(ExternalThreading = true)]
  618.         public IAsyncResult BeginSend(byte[] datagram, int bytes, AsyncCallback requestCallback, object state)
  619.         {
  620.             return BeginSend(datagram, bytes, null, requestCallback, state);
  621.         }
  622.        
  623.        
  624.         public int EndSend(IAsyncResult asyncResult)
  625.         {
  626.             if (m_CleanedUp) {
  627.                 throw new ObjectDisposedException(this.GetType().FullName);
  628.             }
  629.            
  630.             if (m_Active) {
  631.                 return Client.EndSend(asyncResult);
  632.             }
  633.             else {
  634.                 return Client.EndSendTo(asyncResult);
  635.             }
  636.         }
  637.        
  638.        
  639.         /// <devdoc>
  640.         /// <para>
  641.         /// Returns a datagram sent by a server.
  642.         /// </para>
  643.         /// </devdoc>
  644.         public byte[] Receive(ref IPEndPoint remoteEP)
  645.         {
  646.             //
  647.             // parameter validation
  648.             //
  649.             if (m_CleanedUp) {
  650.                 throw new ObjectDisposedException(this.GetType().FullName);
  651.             }
  652.            
  653.             EndPoint tempRemoteEP;
  654.            
  655.             if (m_Family == AddressFamily.InterNetwork) {
  656.                 tempRemoteEP = IPEndPoint.Any;
  657.             }
  658.             else {
  659.                 tempRemoteEP = IPEndPoint.IPv6Any;
  660.             }
  661.            
  662.             int received = Client.ReceiveFrom(m_Buffer, MaxUDPSize, 0, ref tempRemoteEP);
  663.             remoteEP = (IPEndPoint)tempRemoteEP;
  664.            
  665.            
  666.             // because we don't return the actual length, we need to ensure the returned buffer
  667.             // has the appropriate length.
  668.            
  669.             if (received < MaxUDPSize) {
  670.                 byte[] newBuffer = new byte[received];
  671.                 Buffer.BlockCopy(m_Buffer, 0, newBuffer, 0, received);
  672.                 return newBuffer;
  673.             }
  674.             return m_Buffer;
  675.         }
  676.        
  677.        
  678.         [HostProtection(ExternalThreading = true)]
  679.         public IAsyncResult BeginReceive(AsyncCallback requestCallback, object state)
  680.         {
  681.             //
  682.             // parameter validation
  683.             //
  684.             if (m_CleanedUp) {
  685.                 throw new ObjectDisposedException(this.GetType().FullName);
  686.             }
  687.            
  688.             EndPoint tempRemoteEP;
  689.            
  690.             if (m_Family == AddressFamily.InterNetwork) {
  691.                 tempRemoteEP = IPEndPoint.Any;
  692.             }
  693.             else {
  694.                 tempRemoteEP = IPEndPoint.IPv6Any;
  695.             }
  696.            
  697.             return Client.BeginReceiveFrom(m_Buffer, 0, MaxUDPSize, SocketFlags.None, ref tempRemoteEP, requestCallback, state);
  698.         }
  699.        
  700.        
  701.         public byte[] EndReceive(IAsyncResult asyncResult, ref IPEndPoint remoteEP)
  702.         {
  703.             if (m_CleanedUp) {
  704.                 throw new ObjectDisposedException(this.GetType().FullName);
  705.             }
  706.            
  707.             EndPoint tempRemoteEP;
  708.            
  709.             if (m_Family == AddressFamily.InterNetwork) {
  710.                 tempRemoteEP = IPEndPoint.Any;
  711.             }
  712.             else {
  713.                 tempRemoteEP = IPEndPoint.IPv6Any;
  714.             }
  715.            
  716.             int received = Client.EndReceiveFrom(asyncResult, ref tempRemoteEP);
  717.             remoteEP = (IPEndPoint)tempRemoteEP;
  718.            
  719.             // because we don't return the actual length, we need to ensure the returned buffer
  720.             // has the appropriate length.
  721.            
  722.             if (received < MaxUDPSize) {
  723.                 byte[] newBuffer = new byte[received];
  724.                 Buffer.BlockCopy(m_Buffer, 0, newBuffer, 0, received);
  725.                 return newBuffer;
  726.             }
  727.             return m_Buffer;
  728.         }
  729.        
  730.        
  731.        
  732.         /// <devdoc>
  733.         /// <para>
  734.         /// Joins a multicast address group.
  735.         /// </para>
  736.         /// </devdoc>
  737.         public void JoinMulticastGroup(IPAddress multicastAddr)
  738.         {
  739.             //
  740.             // parameter validation
  741.             //
  742.             if (m_CleanedUp) {
  743.                 throw new ObjectDisposedException(this.GetType().FullName);
  744.             }
  745.            
  746.             //
  747.             // IPv6 Changes: we need to create the correct MulticastOption and
  748.             // must also check for address family compatibility
  749.             //
  750.             if (multicastAddr.AddressFamily != m_Family) {
  751.                 throw new ArgumentException(SR.GetString(SR.net_protocol_invalid_multicast_family, "UDP"), "multicastAddr");
  752.             }
  753.            
  754.             if (m_Family == AddressFamily.InterNetwork) {
  755.                 MulticastOption mcOpt = new MulticastOption(multicastAddr);
  756.                
  757.                 Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcOpt);
  758.             }
  759.             else {
  760.                 IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr);
  761.                
  762.                 Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mcOpt);
  763.             }
  764.         }
  765.        
  766.        
  767.        
  768.         public void JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress)
  769.         {
  770.             //
  771.             // parameter validation
  772.             //
  773.             if (m_CleanedUp) {
  774.                 throw new ObjectDisposedException(this.GetType().FullName);
  775.             }
  776.            
  777.             if (m_Family != AddressFamily.InterNetwork) {
  778.                 throw new SocketException(SocketError.OperationNotSupported);
  779.             }
  780.            
  781.             MulticastOption mcOpt = new MulticastOption(multicastAddr, localAddress);
  782.            
  783.             Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcOpt);
  784.         }
  785.        
  786.        
  787.        
  788.         /// <devdoc>
  789.         /// <para>
  790.         /// Joins an IPv6 multicast address group.
  791.         /// </para>
  792.         /// </devdoc>
  793.         public void JoinMulticastGroup(int ifindex, IPAddress multicastAddr)
  794.         {
  795.             //
  796.             // parameter validation
  797.             //
  798.             if (m_CleanedUp) {
  799.                 throw new ObjectDisposedException(this.GetType().FullName);
  800.             }
  801.            
  802.             if (multicastAddr == null) {
  803.                 throw new ArgumentNullException("multicastAddr");
  804.             }
  805.            
  806.             if (ifindex < 0) {
  807.                 throw new ArgumentException(SR.GetString(SR.net_value_cannot_be_negative), "ifindex");
  808.             }
  809.            
  810.             //
  811.             // Ensure that this is an IPv6 client, otherwise throw WinSock
  812.             // Operation not supported socked exception.
  813.             //
  814.             if (m_Family != AddressFamily.InterNetworkV6) {
  815.                 throw new SocketException(SocketError.OperationNotSupported);
  816.             }
  817.            
  818.             IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr, ifindex);
  819.            
  820.             Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mcOpt);
  821.         }
  822.        
  823.         /// <devdoc>
  824.         /// <para>
  825.         /// Joins a multicast address group with the specified time to live (TTL).
  826.         /// </para>
  827.         /// </devdoc>
  828.         public void JoinMulticastGroup(IPAddress multicastAddr, int timeToLive)
  829.         {
  830.             //
  831.             // parameter validation;
  832.             //
  833.             if (m_CleanedUp) {
  834.                 throw new ObjectDisposedException(this.GetType().FullName);
  835.             }
  836.             if (multicastAddr == null) {
  837.                 throw new ArgumentNullException("multicastAddr");
  838.             }
  839.             if (!ValidationHelper.ValidateRange(timeToLive, 0, 255)) {
  840.                 throw new ArgumentOutOfRangeException("timeToLive");
  841.             }
  842.            
  843.             //
  844.             // join the Multicast Group
  845.             //
  846.             JoinMulticastGroup(multicastAddr);
  847.            
  848.             //
  849.             // set Time To Live (TLL)
  850.             //
  851.             Client.SetSocketOption((m_Family == AddressFamily.InterNetwork) ? SocketOptionLevel.IP : SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, timeToLive);
  852.         }
  853.        
  854.         /// <devdoc>
  855.         /// <para>
  856.         /// Leaves a multicast address group.
  857.         /// </para>
  858.         /// </devdoc>
  859.         public void DropMulticastGroup(IPAddress multicastAddr)
  860.         {
  861.             //
  862.             // parameter validation
  863.             //
  864.             if (m_CleanedUp) {
  865.                 throw new ObjectDisposedException(this.GetType().FullName);
  866.             }
  867.             if (multicastAddr == null) {
  868.                 throw new ArgumentNullException("multicastAddr");
  869.             }
  870.            
  871.             //
  872.             // IPv6 Changes: we need to create the correct MulticastOption and
  873.             // must also check for address family compatibility
  874.             //
  875.             if (multicastAddr.AddressFamily != m_Family) {
  876.                 throw new ArgumentException(SR.GetString(SR.net_protocol_invalid_multicast_family, "UDP"), "multicastAddr");
  877.             }
  878.            
  879.             if (m_Family == AddressFamily.InterNetwork) {
  880.                 MulticastOption mcOpt = new MulticastOption(multicastAddr);
  881.                
  882.                 Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, mcOpt);
  883.             }
  884.             else {
  885.                 IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr);
  886.                
  887.                 Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mcOpt);
  888.             }
  889.         }
  890.        
  891.         /// <devdoc>
  892.         /// <para>
  893.         /// Leaves an IPv6 multicast address group.
  894.         /// </para>
  895.         /// </devdoc>
  896.         public void DropMulticastGroup(IPAddress multicastAddr, int ifindex)
  897.         {
  898.             //
  899.             // parameter validation
  900.             //
  901.             if (m_CleanedUp) {
  902.                 throw new ObjectDisposedException(this.GetType().FullName);
  903.             }
  904.            
  905.             if (multicastAddr == null) {
  906.                 throw new ArgumentNullException("multicastAddr");
  907.             }
  908.            
  909.             if (ifindex < 0) {
  910.                 throw new ArgumentException(SR.GetString(SR.net_value_cannot_be_negative), "ifindex");
  911.             }
  912.            
  913.             //
  914.             // Ensure that this is an IPv6 client, otherwise throw WinSock
  915.             // Operation not supported socked exception.
  916.             //
  917.             if (m_Family != AddressFamily.InterNetworkV6) {
  918.                 throw new SocketException(SocketError.OperationNotSupported);
  919.             }
  920.            
  921.             IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr, ifindex);
  922.            
  923.             Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mcOpt);
  924.         }
  925.        
  926.         private void createClientSocket()
  927.         {
  928.             //
  929.             // common initialization code
  930.             //
  931.             // IPv6 Changes: Use the AddressFamily of this class rather than hardcode.
  932.             //
  933.             Client = new Socket(m_Family, SocketType.Dgram, ProtocolType.Udp);
  934.         }
  935.        
  936.     }
  937.     // class UdpClient
  938.    
  939.    
  940. }
  941. // namespace System.Net.Sockets

Developer Fusion