-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathSocketServer.cs
147 lines (136 loc) · 4.17 KB
/
SocketServer.cs
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using IotWeb.Common;
namespace IotWeb.Server
{
public class SocketServer : ISocketServer
{
// Constants
private const int BackLog = 5; // Maximum pending requests
// Instance variables
private ConnectionHandler m_handler;
private Socket m_listener;
public int Port { get; private set; }
public ConnectionHandler ConnectionRequested
{
get
{
return m_handler;
}
set
{
lock (this)
{
if (Running)
throw new InvalidOperationException("Cannot change handler while server is running.");
m_handler = value;
}
}
}
public bool Running { get; private set; }
public event ServerStoppedHandler ServerStopped;
/// <summary>
/// Constructor with a port to listen on
/// </summary>
/// <param name="port"></param>
public SocketServer(int port)
{
Port = port;
}
public void Start()
{
// Make sure we are not already running
lock (this)
{
if (Running)
throw new InvalidOperationException("Socket server is already running.");
Running = true;
}
// Set up the listener and bind
ThreadPool.QueueUserWorkItem((arg) =>
{
m_listener = new Socket(SocketType.Stream, ProtocolType.IP);
m_listener.Bind(new IPEndPoint(IPAddress.Any, Port));
m_listener.Blocking = true;
m_listener.ReceiveTimeout = 100;
m_listener.Listen(BackLog);
// Wait for incoming connections
while (true)
{
lock (this)
{
if (!Running)
break;
}
try
{
Socket client;
try
{
client = m_listener.Accept();
}
catch (TimeoutException)
{
// Allow recheck of running status
continue;
}
if (m_handler != null)
{
string hostname = "0.0.0.0";
IPEndPoint endpoint = client.RemoteEndPoint as IPEndPoint;
if (endpoint != null)
hostname = endpoint.Address.ToString();
ThreadPool.QueueUserWorkItem((e) =>
{
try
{
if (m_handler != null)
{
client.ReceiveTimeout = 0;
m_handler(
this,
hostname,
new NetworkStream(client, FileAccess.Read, false),
new NetworkStream(client, FileAccess.Write, false)
);
}
}
catch (Exception)
{
// Quietly consume the exception
}
// Finally, we can close the socket
client.Shutdown(SocketShutdown.Both);
client.Close();
});
}
}
catch (Exception)
{
// Quietly consume the exception
}
}
// Fire the stopped events
lock (this)
{
ServerStoppedHandler handler = ServerStopped;
if (handler != null)
handler(this);
}
});
}
public void Stop()
{
lock (this)
{
if (!Running)
return;
// Shutdown the server
Running = false;
}
}
}
}