static void Main(string[] args)
        {
            Console.Title = "Ideal Client - TCP Hole Punching Proof of Concept";

            Peer = new NetworkPeer();
            Peer.OnConnectionAccepted += Peer_OnConnectionAccepted;
            Peer.OnConnectionSuccessful += PeerOnConnectionSuccessful;
            Peer.OnMessageSent += PeerOnMessageSent;
            Peer.OnMessageReceived += Peer_OnMessageReceived;

            Peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
            Peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 1);
            Peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            Console.Write("Bind to which port?: ");
            int portToBind = Int32.Parse(Console.ReadLine());
            Peer.Bind(new IPEndPoint(IPAddress.Any, portToBind));

            Console.Write("Endpoint of your peer: ");

            var introducerEndpoint = Console.ReadLine().Parse();

            Console.WriteLine(String.Format("Connecting to at {0}:{1}...", introducerEndpoint.Address, introducerEndpoint.Port));
            Peer.Connect(introducerEndpoint.Address, introducerEndpoint.Port);

            Console.Write("Press <ENTER> to set socket options back to normal.");
            Console.ReadLine();
            Peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 4);

            Application.Run();
        }
        static void Main(string[] args)
        {
            Console.Title = "Peer - TCP Hole Punching Proof of Concept";

            ListenSocket = new NetworkPeer();
            ListenSocket.OnConnectionAccepted += (s, e1) => Console.WriteLine("ListenSocket.OnConnectionAccepted");
            ListenSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
            ListenSocket.Listen();
            Console.WriteLine(String.Format("Listening for clients on {0}...", ListenSocket.Socket.LocalEndPoint));

            IntroducerSocket = new NetworkPeer();
            IntroducerSocket.OnConnectionAccepted += Peer_OnConnectionAccepted;
            IntroducerSocket.OnConnectionSuccessful += PeerOnConnectionSuccessful;
            IntroducerSocket.OnMessageSent += PeerOnMessageSent;
            IntroducerSocket.OnMessageReceived += Peer_OnMessageReceived;

            IntroducerSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));

            Console.Write("Endpoint of the introducer (try 50.18.245.235:1618): ");

            var input = Console.ReadLine();
            input = (String.IsNullOrEmpty(input)) ? "50.18.245.235:1618" : input;
            var introducerEndpoint = input.Parse();

            Console.WriteLine(String.Format("Connecting to the Introducer at {0}:{1}...", introducerEndpoint.Address, introducerEndpoint.Port));
            IntroducerSocket.Connect(introducerEndpoint.Address, introducerEndpoint.Port);

            Application.Run();
        }
        static void Main(string[] args)
        {
            Console.Title = "Ideal Server - TCP Hole Punching Proof of Concept";

            Incoming = new NetworkPeer();

            Incoming.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
            Incoming.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            Console.Write("Incoming: Bind to which port?: ");
            int portToBind = Int32.Parse(Console.ReadLine());
            Incoming.Bind(new IPEndPoint(IPAddress.Any, portToBind));
            Incoming.Listen();

            Console.WriteLine(String.Format("Listening for clients on {0}...", Incoming.Socket.LocalEndPoint));
            Console.ReadLine();

            Outgoing = new NetworkPeer();

            Outgoing.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
            Outgoing.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            Console.Write("Outgoing: Bind to which port?: ");
            Outgoing.Bind(new IPEndPoint(IPAddress.Any, portToBind));
            Console.Write("Endpoint of your peer: ");

            var introducerEndpoint = Console.ReadLine().Parse();

            Console.WriteLine(String.Format("Connecting to at {0}:{1}...", introducerEndpoint.Address, introducerEndpoint.Port));
            Outgoing.Connect(introducerEndpoint.Address, introducerEndpoint.Port);

            Console.ReadLine();

            Application.Run();
        }
        static void Peer_OnMessageReceived(object sender, MessageReceivedEventArgs e)
        {
            switch (e.MessageType)
            {
                case MessageType.ResponseIntroducerRegistration:
                    {
                        var message = new ResponseIntroducerRegistrationMessage();
                        message.ReadPayload(e.MessageReader);

                        Console.WriteLine(String.Format("Introducer: You have been registered as \"{0}\".", message.RegisteredEndPoint));

                        Console.Write("Endpoint of your peer: ");

                        var peerEndPoint = Console.ReadLine().Parse();

                        Console.WriteLine(String.Format("Requesting an introduction to {0}:{1}...", peerEndPoint.Address, peerEndPoint.Port));
                        IntroducerSocket.Send(new RequestIntroducerIntroductionMessage() { InternalOwnEndPoint = (IPEndPoint) IntroducerSocket.Socket.LocalEndPoint, ExternalPeerEndPoint = peerEndPoint} );
                    }
                    break;
                case MessageType.ResponseIntroducerIntroduction:
                    {
                        var message = new ResponseIntroducerIntroductionMessage();
                        message.ReadPayload(e.MessageReader);

                        Console.WriteLine(String.Format("Introducer: Your peer's internal endpoint is \"{0}\".", message.InternalPeerEndPoint));
                        Console.WriteLine(String.Format("Introducer: Your peer's external endpoint is \"{0}\".", message.ExternalPeerEndPoint));

                        ConnectSocketInternal = new NetworkPeer();
                        ConnectSocketInternal.Bind(new IPEndPoint(IPAddress.Any, PORT));
                        Console.WriteLine(String.Format("Connecting to your peer's internal endpoint..."));
                        ConnectSocketInternal.OnConnectionSuccessful += (s, e1) => Console.WriteLine("ConnectSocketInternal.OnConnectionSuccessful");
                        ConnectSocketInternal.Connect(message.InternalPeerEndPoint.Address, message.InternalPeerEndPoint.Port);

                        ConnectSocketExternal = new NetworkPeer();
                        ConnectSocketExternal.Bind(new IPEndPoint(IPAddress.Any, PORT));
                        Console.WriteLine(String.Format("Connecting to your peer's external endpoint..."));
                        ConnectSocketExternal.OnConnectionSuccessful += (s, e1) => Console.WriteLine("ConnectSocketExternal.OnConnectionSuccessful");
                        ConnectSocketExternal.Connect(message.ExternalPeerEndPoint.Address, message.ExternalPeerEndPoint.Port);
                    }
                    break;
            }
        }