27
|
1 using System;
|
|
2 using System.Net;
|
|
3 using System.Net.Sockets;
|
|
4 using System.Text;
|
|
5 using System.Threading;
|
|
6 using Common.Messages;
|
|
7 using GalaSoft.MvvmLight.Messaging;
|
|
8 using Server.Interfaces;
|
|
9
|
|
10 namespace Server.Listeners
|
|
11 {
|
|
12 public class AsyncSocketListener : IListener
|
|
13 {
|
|
14 public bool IsListening { get; set; }
|
|
15 private readonly int _portNumber;
|
|
16
|
|
17 // Thread signal.
|
|
18 public static ManualResetEvent AllDone = new ManualResetEvent(false);
|
|
19
|
|
20 public AsyncSocketListener(int portNumber)
|
|
21 {
|
|
22 IsListening = false;
|
|
23 _portNumber = portNumber;
|
|
24 }
|
|
25
|
|
26 public void Start()
|
|
27 {
|
28
|
28 if (IsListening)
|
|
29 {
|
|
30 Messenger.Default.Send(new SocketLogMessage() { Body = "Already listening..." });
|
|
31 return;
|
|
32 }
|
|
33 Messenger.Default.Send(new SocketLogMessage() { Body = "Opening listener..." });
|
27
|
34
|
|
35 // Data buffer for incoming data.
|
|
36 var bytes = new Byte[1024];
|
|
37
|
|
38 // Establish the local endpoint for the socket
|
|
39 var ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
|
|
40 var ipAddress = ipHostInfo.AddressList[2];
|
|
41 var localEndPoint = new IPEndPoint(ipAddress, _portNumber);
|
|
42
|
|
43 // Create a TCP/IP socket.
|
|
44 using(var listener = new Socket(
|
|
45 AddressFamily.InterNetwork,
|
|
46 SocketType.Stream,
|
|
47 ProtocolType.Tcp))
|
|
48 {
|
|
49
|
|
50 // Bind the socket to the local endpoint and listen for incoming connections.
|
28
|
51 try
|
|
52 {
|
|
53 listener.Bind(localEndPoint);
|
|
54 listener.Listen(100);
|
|
55 IsListening = true;
|
|
56
|
|
57 Messenger.Default.Send(new SocketLogMessage() { Body = "Listener opened" });
|
27
|
58
|
28
|
59 while (IsListening)
|
|
60 {
|
|
61 // Set the event to nonsignaled state.
|
|
62 AllDone.Reset();
|
27
|
63
|
28
|
64 // Start an asynchronous socket to listen for connections.
|
|
65 Messenger.Default.Send(new SocketLogMessage() { Body = "Waiting for a connection..." });
|
|
66
|
|
67 listener.BeginAccept(
|
|
68 AcceptCallback,
|
|
69 listener);
|
27
|
70
|
28
|
71 // Wait until a connection is made before continuing.
|
|
72 AllDone.WaitOne();
|
|
73 }
|
|
74
|
|
75 if (listener.Connected)
|
|
76 {
|
|
77 Messenger.Default.Send(new SocketLogMessage() { Body = "Shutting down listener..." });
|
|
78 listener.Shutdown(SocketShutdown.Both);
|
27
|
79
|
28
|
80 Messenger.Default.Send(new SocketLogMessage() { Body = "Disconnecting listener..." });
|
|
81 listener.Disconnect(true);
|
|
82 }
|
|
83
|
27
|
84 }
|
28
|
85 catch (Exception e)
|
|
86 {
|
|
87 Messenger.Default.Send(new SocketLogMessage() { Body = e.Message });
|
|
88 }
|
|
89 finally
|
|
90 {
|
|
91 Messenger.Default.Send(new SocketLogMessage() { Body = "Connection closed." });
|
|
92 }
|
27
|
93 }
|
|
94 }
|
|
95
|
|
96 public void AcceptCallback(IAsyncResult ar)
|
|
97 {
|
|
98 // Signal the main thread to continue.
|
|
99 AllDone.Set();
|
|
100
|
|
101 // Get the socket that handles the client request.
|
|
102 var listener = (Socket) ar.AsyncState;
|
|
103 var handler = listener.EndAccept(ar);
|
|
104
|
|
105 // Create the state object.
|
|
106 var state = new StateObject {WorkSocket = handler};
|
|
107
|
|
108 handler.BeginReceive(
|
|
109 state.Buffer,
|
|
110 0,
|
|
111 StateObject.BufferSize,
|
|
112 0,
|
|
113 ReadCallback,
|
|
114 state);
|
|
115 }
|
|
116
|
|
117 public void ReadCallback(IAsyncResult ar)
|
|
118 {
|
|
119 var content = String.Empty;
|
|
120
|
|
121 // Retrieve the state object and the handler socket
|
|
122 // from the asynchronous state object.
|
|
123 var state = (StateObject)ar.AsyncState;
|
|
124 var handler = state.WorkSocket;
|
|
125
|
|
126 // Read data from the client socket.
|
|
127 var bytesRead = handler.EndReceive(ar);
|
|
128
|
|
129 if (bytesRead <= 0) return;
|
|
130
|
|
131 // There might be more data, so store the data received so far.
|
|
132 state.Sb.Append(
|
|
133 Encoding.ASCII.GetString(
|
|
134 state.Buffer,
|
|
135 0,
|
|
136 bytesRead));
|
|
137
|
|
138 // Check for end-of-file tag. If it is not there, read
|
|
139 // more data.
|
|
140 content = state.Sb.ToString();
|
|
141 if (content.IndexOf("<EOF>") > -1)
|
|
142 {
|
|
143 // All the data has been read from the
|
|
144 // client. Display it on the console.
|
|
145
|
|
146 Messenger.Default.Send(
|
|
147 new SocketLogMessage()
|
|
148 {
|
|
149 Body = string.Format(
|
|
150 "Read {0} bytes from socket. \n Data : {1}",
|
|
151 content.Length,
|
|
152 content)
|
|
153 });
|
|
154
|
|
155 // Echo the data back to the client.
|
|
156 Send(handler, "The following message was received: " + content);
|
|
157 }
|
|
158 else
|
|
159 {
|
|
160 // Not all data received. Get more.
|
|
161 handler.BeginReceive(
|
|
162 state.Buffer,
|
|
163 0,
|
|
164 StateObject.BufferSize,
|
|
165 0,
|
|
166 ReadCallback,
|
|
167 state);
|
|
168 }
|
|
169 }
|
|
170
|
|
171 private void Send(Socket handler, String data)
|
|
172 {
|
|
173 // Convert the string data to byte data using ASCII encoding.
|
|
174 var byteData = Encoding.ASCII.GetBytes(data);
|
|
175
|
|
176 // Begin sending the data to the remote device.
|
|
177 handler.BeginSend(
|
|
178 byteData,
|
|
179 0,
|
|
180 byteData.Length,
|
|
181 0,
|
|
182 SendCallback,
|
|
183 handler);
|
|
184 }
|
|
185
|
|
186 private void SendCallback(IAsyncResult ar)
|
|
187 {
|
|
188 try
|
|
189 {
|
|
190 // Retrieve the socket from the state object.
|
|
191 var handler = (Socket)ar.AsyncState;
|
|
192
|
|
193 // Complete sending the data to the remote device.
|
|
194 var bytesSent = handler.EndSend(ar);
|
|
195
|
|
196 Messenger.Default.Send(new SocketLogMessage() { Body = string.Format("Sent {0} bytes to client.", bytesSent) });
|
|
197
|
|
198 handler.Shutdown(SocketShutdown.Both);
|
|
199 handler.Close();
|
|
200 }
|
|
201 catch (Exception e)
|
|
202 {
|
|
203 Messenger.Default.Send(new SocketLogMessage() { Body = e.Message });
|
|
204 }
|
|
205 }
|
|
206
|
|
207 public void Stop()
|
|
208 {
|
|
209 if (IsListening == false) return;
|
|
210
|
|
211 Messenger.Default.Send(new SocketLogMessage() { Body = "Closing connection..." });
|
|
212 IsListening = false;
|
28
|
213 AllDone.Set();
|
27
|
214 }
|
|
215 }
|
28
|
216
|
|
217 // State object for reading client data asynchronously
|
|
218 public class StateObject
|
|
219 {
|
|
220 // Client socket.
|
|
221 public Socket WorkSocket;
|
|
222
|
|
223 // Size of receive buffer.
|
|
224 public const int BufferSize = 1024;
|
|
225
|
|
226 // Receive buffer.
|
|
227 public byte[] Buffer = new byte[BufferSize];
|
|
228
|
|
229 // Received data string.
|
|
230 public StringBuilder Sb = new StringBuilder();
|
|
231 }
|
27
|
232 } |