2 // System.Net.Sockets.UdpClient.cs
\r
5 // Gonzalo Paniagua Javier <gonzalo@ximian.com>
\r
7 // Copyright (C) Ximian, Inc. http://www.ximian.com
\r
13 namespace System.Net.Sockets
\r
15 public class UdpClient : IDisposable
\r
17 private bool disposed = false;
\r
18 private bool active = false;
\r
19 private Socket socket;
\r
20 private AddressFamily family = AddressFamily.InterNetwork;
\r
22 #region Constructors
\r
23 public UdpClient () : this(AddressFamily.InterNetwork)
\r
27 public UdpClient(AddressFamily family)
\r
29 if(family != AddressFamily.InterNetwork && family != AddressFamily.InterNetwork)
\r
30 throw new ArgumentException("family");
\r
32 this.family = family;
\r
36 public UdpClient (int port)
\r
38 if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
\r
39 throw new ArgumentOutOfRangeException ("port");
\r
41 this.family = AddressFamily.InterNetwork;
\r
43 IPEndPoint localEP = new IPEndPoint (IPAddress.Any, port);
\r
44 InitSocket (localEP);
\r
47 public UdpClient (IPEndPoint localEP)
\r
49 if (localEP == null)
\r
50 throw new ArgumentNullException ("localEP");
\r
52 this.family = localEP.AddressFamily;
\r
54 InitSocket (localEP);
\r
57 public UdpClient (string hostname, int port)
\r
59 if (hostname == null)
\r
60 throw new ArgumentNullException ("hostname");
\r
62 if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
\r
63 throw new ArgumentOutOfRangeException ("port");
\r
66 Connect (hostname, port);
\r
69 private void InitSocket (EndPoint localEP)
\r
71 if(socket != null) {
\r
76 socket = new Socket (family, SocketType.Dgram, ProtocolType.Udp);
\r
78 if (localEP != null)
\r
79 socket.Bind (localEP);
\r
82 #endregion // Constructors
\r
83 #region Public methods
\r
85 public void Close ()
\r
87 ((IDisposable) this).Dispose ();
\r
91 public void Connect (IPEndPoint endPoint)
\r
94 if (endPoint == null)
\r
95 throw new ArgumentNullException ("endPoint");
\r
97 socket.Connect (endPoint);
\r
101 public void Connect (IPAddress addr, int port)
\r
104 throw new ArgumentNullException ("addr");
\r
106 if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
\r
107 throw new ArgumentOutOfRangeException ("port");
\r
109 Connect (new IPEndPoint (addr, port));
\r
112 public void Connect (string hostname, int port)
\r
114 if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
\r
115 throw new ArgumentOutOfRangeException ("port");
\r
117 IPAddress[] addresses = Dns.Resolve (hostname).AddressList;
\r
118 for(int i=0; i<addresses.Length; i++) {
\r
120 this.family = addresses[i].AddressFamily;
\r
121 Connect (new IPEndPoint (addresses[i], port));
\r
123 } catch(Exception e) {
\r
124 if(i == addresses.Length - 1){
\r
125 if(socket != null) {
\r
130 /// This is the last entry, re-throw the exception
\r
137 #region Multicast methods
\r
138 public void DropMulticastGroup (IPAddress multicastAddr)
\r
141 if (multicastAddr == null)
\r
142 throw new ArgumentNullException ("multicastAddr");
\r
144 if(family == AddressFamily.InterNetwork)
\r
145 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DropMembership,
\r
146 new MulticastOption (multicastAddr));
\r
149 socket.SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DropMembership,
\r
150 new IPv6MulticastOption (multicastAddr));
\r
154 public void JoinMulticastGroup (IPAddress multicastAddr)
\r
158 if(family == AddressFamily.InterNetwork)
\r
159 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.AddMembership,
\r
160 new MulticastOption (multicastAddr));
\r
163 socket.SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.AddMembership,
\r
164 new IPv6MulticastOption (multicastAddr));
\r
168 public void JoinMulticastGroup (IPAddress multicastAddr, int timeToLive)
\r
171 JoinMulticastGroup (multicastAddr);
\r
172 if (timeToLive < 0 || timeToLive > 255)
\r
173 throw new ArgumentOutOfRangeException ("timeToLive");
\r
175 if(family == AddressFamily.InterNetwork)
\r
176 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive,
\r
180 socket.SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive,
\r
186 public byte [] Receive (ref IPEndPoint remoteEP)
\r
190 // Bug 45633: the spec states that we should block until a datagram arrives:
\r
191 // remove the 512 hardcoded value.
\r
193 // Block until we get it.
\r
194 socket.Poll (-1, SelectMode.SelectRead);
\r
197 int available = socket.Available;
\r
199 recBuffer = new byte [available];
\r
200 EndPoint endPoint = new IPEndPoint (IPAddress.Any, 0);
\r
201 int dataRead = socket.ReceiveFrom (recBuffer, ref endPoint);
\r
202 if (dataRead < recBuffer.Length)
\r
203 recBuffer = CutArray (recBuffer, dataRead);
\r
205 remoteEP = (IPEndPoint) endPoint;
\r
209 public int Send (byte [] dgram, int bytes)
\r
213 throw new ArgumentNullException ("dgram");
\r
216 throw new InvalidOperationException ("Operation not allowed on " +
\r
217 "non-connected sockets.");
\r
219 return socket.Send (dgram, 0, bytes, SocketFlags.None);
\r
222 public int Send (byte [] dgram, int bytes, IPEndPoint endPoint)
\r
226 throw new ArgumentNullException ("dgram is null");
\r
229 if (endPoint != null)
\r
230 throw new InvalidOperationException ("Cannot send packets to an " +
\r
231 "arbitrary host while connected.");
\r
233 return socket.Send (dgram, 0, bytes, SocketFlags.None);
\r
236 return socket.SendTo (dgram, 0, bytes, SocketFlags.None, endPoint);
\r
239 public int Send (byte [] dgram, int bytes, string hostname, int port)
\r
241 return Send (dgram, bytes,
\r
242 new IPEndPoint (Dns.Resolve (hostname).AddressList [0], port));
\r
245 private byte [] CutArray (byte [] orig, int length)
\r
247 byte [] newArray = new byte [length];
\r
248 Buffer.BlockCopy (orig, 0, newArray, 0, length);
\r
254 protected bool Active {
\r
255 get { return active; }
\r
256 set { active = value; }
\r
259 protected Socket Client {
\r
260 get { return socket; }
\r
261 set { socket = value; }
\r
265 void IDisposable.Dispose ()
\r
268 GC.SuppressFinalize (this);
\r
271 void Dispose (bool disposing)
\r
278 if (socket != null)
\r
290 private void CheckDisposed ()
\r
293 throw new ObjectDisposedException (GetType().FullName);
\r