aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Transport/Servers/TcpServer.cs
blob: c8453fb253472329d727b1da341b4be5365c2228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.Logging;

namespace Tango.Transport.Servers
{
    /// <summary>
    /// Represents a TCP/IP listener wrapper.
    /// </summary>
    public class TcpServer
    {
        private TaskScheduler scheduler;
        private LogManager LogManager = LogManager.Default;

        /// <summary>
        /// The TcpListener that is encapsulated behind this Server instance.
        /// </summary>
        public TcpListener Listener { get; set; }
        /// <summary>
        /// The Port that is used to listen to incoming connections.
        /// </summary>
        public int Port { get; set; }
        /// <summary>
        /// Returns true if the Server instance is running.
        /// </summary>
        public bool IsStarted { get; private set; }

        #region Events

        public event EventHandler<ClientConnectedEventArgs> ClientConnected;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new Server instance.
        /// </summary>
        /// <param name="port">The port number that is used to listen for incoming connections.</param>
        public TcpServer(int port)
        {
            Port = port;
        }
        #endregion

        #region Public Methods

        /// <summary>
        /// Start Listening for incoming connections.
        /// </summary>
        public void Start()
        {
            if (!IsStarted)
            {
                if (scheduler == null)
                {
                    scheduler = TaskScheduler.FromCurrentSynchronizationContext();
                }

                Listener = new TcpListener(System.Net.IPAddress.Any, Port);
                Listener.Start();
                IsStarted = true;
                LogManager.Log("Server Started!");
                WaitForConnection();
            }
        }
        /// <summary>
        /// Stop listening for incoming connections.
        /// </summary>
        public void Stop()
        {
            if (IsStarted)
            {
                Listener.Stop();
                IsStarted = false;
                LogManager.Log("Server Stopped!");
            }
        }

        #endregion

        #region Incoming Connections Methods

        private void WaitForConnection()
        {
            Listener.BeginAcceptTcpClient(new AsyncCallback(ConnectionHandler), null);
        }

        private void ConnectionHandler(IAsyncResult ar)
        {
            if (IsStarted)
            {
                try
                {
                    OnClientConnected(Listener.EndAcceptTcpClient(ar));
                    WaitForConnection();
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (ObjectDisposedException ex)
#pragma warning restore CS0168 // Variable is declared but never used
                {
                    //Ignore..
                }
            }
        }

        #endregion

        #region Virtual Methods

        protected virtual void OnClientConnected(TcpClient socket)
        {
            LogManager.Log("New client connected.");

            Task.Factory.StartNew(() => 
            {

                ClientConnected?.Invoke(this, new ClientConnectedEventArgs(socket));

            },CancellationToken.None,TaskCreationOptions.None,scheduler);
        }

        #endregion
    }
}