// System.Net.Sockets.TcpListener.cs // // Authors: // Phillip Pearson (pp@myelin.co.nz) // Gonzalo Paniagua Javier (gonzalo@ximian.com) // Patrik Torstensson // // Copyright (C) 2001, Phillip Pearson // http://www.myelin.co.nz // // (c) 2003 Ximian, Inc. (http://www.ximian.com) // (c) 2004 Novell, Inc. // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Net; namespace System.Net.Sockets { /// /// A slightly more abstracted way to listen for incoming /// network connections than a Socket. /// public class TcpListener { // private data bool active; Socket server; EndPoint savedEP; // constructor /// /// Some code that is shared between the constructors. /// private void Init (AddressFamily family, EndPoint ep) { active = false; server = new Socket(family, SocketType.Stream, ProtocolType.Tcp); savedEP = ep; } /// /// Constructs a new TcpListener to listen on a specified port /// /// The port to listen on, e.g. 80 if you /// are a web server #if NET_1_1 [Obsolete ("Use TcpListener (IPAddress address, int port) instead")] #endif public TcpListener (int port) { if (port < 0 || port > 65535) throw new ArgumentOutOfRangeException ("port"); Init (AddressFamily.InterNetwork, new IPEndPoint (IPAddress.Any, port)); } /// /// Constructs a new TcpListener with a specified local endpoint /// /// The endpoint public TcpListener (IPEndPoint local_end_point) { if (local_end_point == null) throw new ArgumentNullException ("local_end_point"); Init (local_end_point.AddressFamily, local_end_point); } /// /// Constructs a new TcpListener, listening on a specified port /// and IP (for use on a multi-homed machine) /// /// The IP to listen on /// The port to listen on public TcpListener (IPAddress listen_ip, int port) { if (listen_ip == null) throw new ArgumentNullException ("listen_ip"); if (port < 0 || port > 65535) throw new ArgumentOutOfRangeException ("port"); Init (listen_ip.AddressFamily, new IPEndPoint(listen_ip, port)); } // properties /// /// A flag that is 'true' if the TcpListener is listening, /// or 'false' if it is not listening /// protected bool Active { get { return active; } } /// /// The local end point /// public EndPoint LocalEndpoint { get { if (active) return server.LocalEndPoint; return savedEP; } } /// /// The listening socket /// protected Socket Server { get { return server; } } // methods /// /// Accepts a pending connection /// /// A Socket object for the new connection public Socket AcceptSocket () { if (!active) throw new InvalidOperationException ("Socket is not listening"); return server.Accept(); } /// /// Accepts a pending connection /// /// A TcpClient /// object made from the new socket. public TcpClient AcceptTcpClient () { if (!active) throw new InvalidOperationException ("Socket is not listening"); Socket clientSocket = server.Accept (); TcpClient client = new TcpClient(); // use internal method SetTcpClient to make a // client with the specified socket client.SetTcpClient (clientSocket); return client; } /// /// Destructor - stops the listener listening /// ~TcpListener () { if (active) Stop(); } /// /// Returns 'true' if there is a connection waiting to be accepted /// with AcceptSocket() or AcceptTcpClient(). /// public bool Pending () { if (!active) throw new InvalidOperationException ("Socket is not listening"); return server.Poll(0, SelectMode.SelectRead); } /// /// Tells the TcpListener to start listening. /// public void Start () { if (active) return; if (server == null) throw new InvalidOperationException("Invalid server socket"); server.Bind (savedEP); // MS: sets Listen to Int32.MaxValue server.Listen(5); // According to the man page some BSD and BSD-derived // systems limit the backlog to 5. This should really be // configurable though active = true; } /// /// Tells the TcpListener to stop listening and dispose /// of all managed resources. /// public void Stop () { if (active) { server.Close (); server = null; } Init (AddressFamily.InterNetwork, savedEP); } } }