View difference between Paste ID: ELyBNp68 and 28zRZGx1
SHOW: | | - or go back to the newest paste.
1
using System;
2
using System.Collections.Generic;
3
using System.Net;
4
using System.Net.Sockets;
5
using System.Linq;
6
using System.Text;
7
using System.Threading;
8
9
namespace Phurious.Android.Blazr
10
{
11
    /// <summary>
12
    /// An Asynchronous TCP Server that makes use of system managed threads
13
    /// and callbacks to stop the server ever locking up.
14
    /// </summary>
15
    public class AsyncTcpServer
16
    {
17
        /// <summary>
18
        /// The encoding to use when sending / receiving strings.
19
        /// </summary>
20
        public Encoding Encoding { get; set; }
21
22
        private TcpListener _tcpListener;
23
        private List<AsyncTcpClient> _clients;
24
 
25
        /// <summary>
26
        /// Constructor for a new server using an IPAddress and Port
27
        /// </summary>
28
        /// <param name="localaddr">The Local IP Address for the server.</param>
29
        /// <param name="port">The port for the server.</param>
30
        public AsyncTcpServer(IPAddress localaddr, int port)
31
            : this()
32
        {
33
            _tcpListener = new TcpListener(localaddr, port);
34
        }
35
 
36
        /// <summary>
37
        /// Constructor for a new server using an end point
38
        /// </summary>
39
        /// <param name="localEP">The local end point for the server.</param>
40
        public AsyncTcpServer(IPEndPoint localEP)
41
            : this()
42
        {
43
            _tcpListener = new TcpListener(localEP);
44
        }
45
 
46
        /// <summary>
47
        /// Private constructor for the common constructor operations.
48
        /// </summary>
49
        private AsyncTcpServer()
50
        {
51
            this.Encoding = Encoding.ASCII;
52
            this._clients = new List<AsyncTcpClient>();
53
        }
54
 
55
        /// <summary>
56
        /// An enumerable collection of all the currently connected tcp clients
57
        /// </summary>
58
        public IEnumerable<TcpClient> TcpClients
59
        {
60
            get
61
            {
62
                foreach (AsyncTcpClient client in this._clients)
63
                {
64
                    yield return client.TcpClient;
65
                }
66
            }
67
        }
68
 
69
        /// <summary>
70
        /// Starts the TCP Server listening for new clients.
71
        /// </summary>
72
        public void Listen()
73
        {
74
            this._tcpListener.Start();
75
            this._tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
76
        }
77
78
 
79
80
        /// <summary>
81
        /// Stops the TCP Server listening for new clients and disconnects
82
        /// any currently connected clients.
83
        /// </summary>
84
        public void StopListening()
85
        {
86
            this._tcpListener.Stop();
87
            lock (this._clients)
88
            {
89
                foreach (AsyncTcpClient client in this._clients)
90
                {
91
                    client.TcpClient.Client.Disconnect(false);
92
                }
93
94
                this._clients.Clear();
95
            }
96
        }
97
98
        /// <summary>
99
        /// Writes a string to a given TCP Client
100
        /// </summary>
101
        /// <param name="tcpClient">The client to write to</param>
102
        /// <param name="data">The string to send.</param>
103
        public void Write(TcpClient tcpClient, String data)
104
        {
105
            byte[] bytes = this.Encoding.GetBytes(data);
106
107
            Write(tcpClient, bytes);
108
        }
109
110
 
111
112
        /// <summary>
113
        /// Writes a string to all clients connected.
114
        /// </summary>
115
        /// <param name="data">The string to send.</param>
116
        public void Write(String data)
117
        {
118
            foreach (AsyncTcpClient client in this._clients)
119
            {
120
                Write(client.TcpClient, data);
121
            }
122
        }
123
124
        /// <summary>
125
        /// Writes a byte array to all clients connected.
126
        /// </summary>
127
        /// <param name="bytes">The bytes to send.</param>
128
        public void Write(Byte[] bytes)
129
        {
130
            foreach (AsyncTcpClient client in this._clients)
131
            {
132
                Write(client.TcpClient, bytes);
133
            }
134
        }
135
136
        /// <summary>
137
        /// Writes a byte array to a given TCP Client
138
        /// </summary>
139
        /// <param name="tcpClient">The client to write to</param>
140
        /// <param name="bytes">The bytes to send</param>
141
        public void Write(TcpClient tcpClient, Byte[] bytes)
142
        {
143
            NetworkStream networkStream = tcpClient.GetStream();
144
            
145
            networkStream.BeginWrite(bytes, 0, bytes.Length, WriteCallback, tcpClient);
146
        }
147
148
        public void Write(AsyncTcpClient client, Byte[] bytes)
149
        {
150
            NetworkStream networkStream = client.NetworkStream;
151
            
152
            networkStream.BeginWrite(bytes, 0, bytes.Length, WriteCallback, client.TcpClient);
153
        }
154
155
        /// <summary>
156
        /// Callback for the write opertaion.
157
        /// </summary>
158
        /// <param name="result">The async result object</param>
159
        private void WriteCallback(IAsyncResult result)
160
        {
161
            TcpClient tcpClient = result.AsyncState as TcpClient;
162
            NetworkStream networkStream = tcpClient.GetStream();
163
164
            networkStream.EndWrite(result);
165
        }
166
167
        /// <summary>
168
        /// Callback for the accept tcp client opertaion.
169
        /// </summary>
170
        /// <param name="result">The async result object</param>
171
        private void AcceptTcpClientCallback(IAsyncResult result)
172
        {
173
            TcpClient tcpClient = _tcpListener.EndAcceptTcpClient(result);
174
            byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
175
            AsyncTcpClient client = new AsyncTcpClient(tcpClient, buffer);
176
            client.DataReceived += new AsyncTcpClient.DataReceivedHandler(Program.ProcessCommand);
177
178
            lock (this._clients)
179
            {
180
                this._clients.Add(client);
181
            }
182
183
            NetworkStream networkStream = client.NetworkStream;
184
185
            networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
186
187
            _tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
188
        }
189
190
        /// <summary>
191
        /// Callback for the read opertaion.
192
        /// </summary>
193
        /// <param name="result">The async result object</param>
194
        private void ReadCallback(IAsyncResult result)
195
        {
196
            AsyncTcpClient client = result.AsyncState as AsyncTcpClient;
197
198
            if (client == null) return;
199
200
            NetworkStream networkStream = client.NetworkStream;
201
202
            int read = networkStream.EndRead(result);
203
204
            if (read == 0)
205
            {
206
                lock (this._clients)
207
                {
208
                    this._clients.Remove(client);
209
                    return;
210
                }
211
            }
212
213
            string data = this.Encoding.GetString(client.Buffer, 0, read);
214
215
            networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
216
        }
217
    }
218
219
/// <summary>
220
    /// Internal class to join the TCP client and buffer together
221
    /// for easy management in the server
222
    /// </summary>
223
    public class AsyncTcpClient
224
    {
225
        public delegate void DataReceivedHandler(AsyncTcpClient client);
226
        public event DataReceivedHandler DataReceived;
227
 
228
        /// <summary>
229
        /// The encoding to use when sending / receiving strings.
230
        /// </summary>
231
        public Encoding Encoding { get; set; }
232
 
233
        private TcpClient _tcpClient = null;
234
        private Byte[] _buffer = null;
235
 
236
        /// <summary>
237
        /// Constructor for a new Client
238
        /// </summary>
239
        /// <param name="tcpClient">The TCP client</param>
240
        /// <param name="buffer">The byte array buffer</param>
241
        public AsyncTcpClient(TcpClient tcpClient, Byte[] buffer)
242
            : this()
243
        {
244
            if (tcpClient == null) throw new ArgumentNullException("tcpClient is null");
245
 
246
            if (buffer == null) throw new ArgumentNullException("Buffer is null");
247
 
248
            this.TcpClient = tcpClient;
249
 
250
            this.Buffer = buffer;
251
        }
252
 
253
        private AsyncTcpClient()
254
        {
255
            this.Encoding = Encoding.ASCII;
256
        }
257
 
258
        /// <summary>
259
        /// Gets the TCP Client
260
        /// </summary>
261
        public TcpClient TcpClient
262
        {
263
            get
264
            {
265
                return _tcpClient;
266
            }
267
            set
268
            {
269
                _tcpClient = value;
270
            }
271
        }
272
 
273
        /// <summary>
274
        /// Gets the Buffer.
275
        /// </summary>
276
        public Byte[] Buffer
277
        {
278
            get
279
            {
280
                return _buffer;
281
            }
282
            set
283
            {
284
                _buffer = value;
285
                if (this.DataReceived != null) this.DataReceived(this);
286
            }
287
        }
288
 
289
 
290
        /// <summary>
291
        /// Gets the network stream
292
        /// </summary>
293
        public NetworkStream NetworkStream
294
        {
295
            get
296
            {
297
                return TcpClient.GetStream();
298
            }
299
        }
300
    }
301
}