1 // System.Net.Sockets.TcpClient.cs
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Gonzalo Paniagua Javier (gonzalo@novell.com)
6 // Sridhar Kulkarni (sridharkulkarni@gmail.com)
8 // Copyright (C) 2001, Phillip Pearson
9 // http://www.myelin.co.nz
10 // Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 namespace System
.Net
.Sockets
39 public class TcpClient
: IDisposable
{
40 enum Properties
: uint {
43 ReceiveBufferSize
= 4,
55 int recv_timeout
, send_timeout
;
56 int recv_buffer_size
, send_buffer_size
;
57 LingerOption linger_state
;
60 private void Init (AddressFamily family
)
69 client
= new Socket(family
, SocketType
.Stream
, ProtocolType
.Tcp
);
74 Init(AddressFamily
.InterNetwork
);
75 client
.Bind(new IPEndPoint(IPAddress
.Any
, 0));
79 public TcpClient (AddressFamily family
)
81 if (family
!= AddressFamily
.InterNetwork
&&
82 family
!= AddressFamily
.InterNetworkV6
) {
83 throw new ArgumentException ("Family must be InterNetwork or InterNetworkV6", "family");
87 IPAddress any
= IPAddress
.Any
;
88 if (family
== AddressFamily
.InterNetworkV6
)
89 any
= IPAddress
.IPv6Any
;
90 client
.Bind (new IPEndPoint (any
, 0));
94 public TcpClient (IPEndPoint local_end_point
)
96 Init(local_end_point
.AddressFamily
);
97 client
.Bind(local_end_point
);
100 public TcpClient (string hostname
, int port
)
102 Connect(hostname
, port
);
105 protected bool Active
{
106 get { return active; }
107 set { active = value; }
111 public Socket Client
{
113 protected Socket Client
{
115 get { return client; }
123 public int Available
{
124 get { return client.Available; }
127 public bool Connected
{
128 get { return client.Connected; }
132 [MonoNotSupported ("Not supported as Socket.ExclusiveAddressUse is not supported")]
134 public bool ExclusiveAddressUse
{
136 return(client
.ExclusiveAddressUse
);
139 client
.ExclusiveAddressUse
= value;
143 internal void SetTcpClient (Socket s
)
148 public LingerOption LingerState
{
150 if ((values
& Properties
.LingerState
) != 0)
153 return (LingerOption
) client
.GetSocketOption (SocketOptionLevel
.Socket
,
154 SocketOptionName
.Linger
);
157 if (!client
.Connected
) {
158 linger_state
= value;
159 values
|= Properties
.LingerState
;
162 client
.SetSocketOption(
163 SocketOptionLevel
.Socket
,
164 SocketOptionName
.Linger
, value);
168 public bool NoDelay
{
170 if ((values
& Properties
.NoDelay
) != 0)
173 return (bool)client
.GetSocketOption(
174 SocketOptionLevel
.Tcp
,
175 SocketOptionName
.NoDelay
);
178 if (!client
.Connected
) {
180 values
|= Properties
.NoDelay
;
183 client
.SetSocketOption(
184 SocketOptionLevel
.Tcp
,
185 SocketOptionName
.NoDelay
, value ? 1 : 0);
189 public int ReceiveBufferSize
{
191 if ((values
& Properties
.ReceiveBufferSize
) != 0)
192 return recv_buffer_size
;
194 return (int)client
.GetSocketOption(
195 SocketOptionLevel
.Socket
,
196 SocketOptionName
.ReceiveBuffer
);
199 if (!client
.Connected
) {
200 recv_buffer_size
= value;
201 values
|= Properties
.ReceiveBufferSize
;
204 client
.SetSocketOption(
205 SocketOptionLevel
.Socket
,
206 SocketOptionName
.ReceiveBuffer
, value);
210 public int ReceiveTimeout
{
212 if ((values
& Properties
.ReceiveTimeout
) != 0)
215 return (int)client
.GetSocketOption(
216 SocketOptionLevel
.Socket
,
217 SocketOptionName
.ReceiveTimeout
);
220 if (!client
.Connected
) {
221 recv_timeout
= value;
222 values
|= Properties
.ReceiveTimeout
;
225 client
.SetSocketOption(
226 SocketOptionLevel
.Socket
,
227 SocketOptionName
.ReceiveTimeout
, value);
231 public int SendBufferSize
{
233 if ((values
& Properties
.SendBufferSize
) != 0)
234 return send_buffer_size
;
236 return (int)client
.GetSocketOption(
237 SocketOptionLevel
.Socket
,
238 SocketOptionName
.SendBuffer
);
241 if (!client
.Connected
) {
242 send_buffer_size
= value;
243 values
|= Properties
.SendBufferSize
;
246 client
.SetSocketOption(
247 SocketOptionLevel
.Socket
,
248 SocketOptionName
.SendBuffer
, value);
252 public int SendTimeout
{
254 if ((values
& Properties
.SendTimeout
) != 0)
257 return (int)client
.GetSocketOption(
258 SocketOptionLevel
.Socket
,
259 SocketOptionName
.SendTimeout
);
262 if (!client
.Connected
) {
263 send_timeout
= value;
264 values
|= Properties
.SendTimeout
;
267 client
.SetSocketOption(
268 SocketOptionLevel
.Socket
,
269 SocketOptionName
.SendTimeout
, value);
278 ((IDisposable
) this).Dispose ();
281 public void Connect (IPEndPoint remote_end_point
)
284 client
.Connect(remote_end_point
);
291 public void Connect (IPAddress address
, int port
)
293 Connect(new IPEndPoint(address
, port
));
298 Properties props
= values
;
301 if ((props
& Properties
.LingerState
) != 0)
302 LingerState
= linger_state
;
303 if ((props
& Properties
.NoDelay
) != 0)
305 if ((props
& Properties
.ReceiveBufferSize
) != 0)
306 ReceiveBufferSize
= recv_buffer_size
;
307 if ((props
& Properties
.ReceiveTimeout
) != 0)
308 ReceiveTimeout
= recv_timeout
;
309 if ((props
& Properties
.SendBufferSize
) != 0)
310 SendBufferSize
= send_buffer_size
;
311 if ((props
& Properties
.SendTimeout
) != 0)
312 SendTimeout
= send_timeout
;
315 public void Connect (string hostname
, int port
)
317 IPAddress
[] addresses
= Dns
.GetHostAddresses (hostname
);
318 Connect (addresses
, port
);
326 void Connect (IPAddress
[] ipAddresses
, int port
)
330 if (ipAddresses
== null) {
331 throw new ArgumentNullException ("ipAddresses");
334 for(int i
= 0; i
< ipAddresses
.Length
; i
++) {
336 IPAddress address
= ipAddresses
[i
];
338 if (address
.Equals (IPAddress
.Any
) ||
339 address
.Equals (IPAddress
.IPv6Any
)) {
340 throw new SocketException ((int)SocketError
.AddressNotAvailable
);
343 Init (address
.AddressFamily
);
345 if (address
.AddressFamily
== AddressFamily
.InterNetwork
) {
346 client
.Bind (new IPEndPoint (IPAddress
.Any
, 0));
348 } else if (address
.AddressFamily
== AddressFamily
.InterNetworkV6
) {
349 client
.Bind (new IPEndPoint (IPAddress
.IPv6Any
, 0));
352 throw new NotSupportedException ("This method is only valid for sockets in the InterNetwork and InterNetworkV6 families");
355 Connect (new IPEndPoint (address
, port
));
362 } catch (Exception e
) {
363 /* Reinitialise the socket so
364 * other properties still work
365 * (see no-arg constructor)
367 Init (AddressFamily
.InterNetwork
);
369 /* This is the last known
370 * address, so re-throw the
373 if (i
== ipAddresses
.Length
- 1) {
381 public void EndConnect (IAsyncResult asyncResult
)
383 client
.EndConnect (asyncResult
);
387 [MonoNotSupported ("Not supported as Socket.BeginConnect is not supported")]
389 public IAsyncResult
BeginConnect (IPAddress address
, int port
,
390 AsyncCallback callback
,
393 return(client
.BeginConnect (address
, port
, callback
,
398 [MonoNotSupported ("Not supported as Socket.BeginConnect is not supported")]
400 public IAsyncResult
BeginConnect (IPAddress
[] addresses
,
402 AsyncCallback callback
,
405 return(client
.BeginConnect (addresses
, port
, callback
,
410 [MonoNotSupported ("Not supported as Socket.BeginConnect is not supported")]
412 public IAsyncResult
BeginConnect (string host
, int port
,
413 AsyncCallback callback
,
416 return(client
.BeginConnect (host
, port
, callback
,
421 void IDisposable
.Dispose ()
424 GC
.SuppressFinalize (this);
427 protected virtual void Dispose (bool disposing
)
434 // release managed resources
435 NetworkStream s
= stream
;
438 // This closes the socket as well, as the NetworkStream
443 } else if (client
!= null){
455 public NetworkStream
GetStream()
459 stream
= new NetworkStream (client
, true);
462 finally { CheckDisposed (); }
465 private void CheckDisposed ()
468 throw new ObjectDisposedException (GetType().FullName
);