-
Notifications
You must be signed in to change notification settings - Fork 0
/
listener.d
113 lines (96 loc) · 3.25 KB
/
listener.d
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
/*
D listener written by Christopher E. Miller
Modified by Orvid King
This code is public domain.
You may use it for any purpose.
This code has no warranties and is provided 'as-is'.
*/
import std.algorithm : remove;
import std.conv : to;
import std.socket : InternetAddress, Socket, SocketException, SocketSet, TcpSocket;
import std.stdio : writeln, writefln;
void main(string[] args)
{
ushort port;
if (args.length >= 2)
port = to!ushort(args[1]);
else
port = 4444;
auto listener = new TcpSocket();
assert(listener.isAlive);
listener.blocking = false;
listener.bind(new InternetAddress(port));
listener.listen(10);
writefln("Listening on port %d.", port);
enum MAX_CONNECTIONS = 60;
// Room for listener.
auto socketSet = new SocketSet(MAX_CONNECTIONS + 1);
Socket[] reads;
while (true)
{
socketSet.add(listener);
foreach (sock; reads)
socketSet.add(sock);
Socket.select(socketSet, null, null);
for (size_t i = 0; i < reads.length; i++)
{
if (socketSet.isSet(reads[i]))
{
char[1024] buf;
auto datLength = reads[i].receive(buf[]);
if (datLength == Socket.ERROR)
writeln("Connection error.");
else if (datLength != 0)
{
writefln("Received %d bytes from %s: \"%s\"", datLength, reads[i].remoteAddress().toString(), buf[0..datLength]);
continue;
}
else
{
try
{
// if the connection closed due to an error, remoteAddress() could fail
writefln("Connection from %s closed.", reads[i].remoteAddress().toString());
}
catch (SocketException)
{
writeln("Connection closed.");
}
}
// release socket resources now
reads[i].close();
reads = reads.remove(i);
// i will be incremented by the for, we don't want it to be.
i--;
writefln("\tTotal connections: %d", reads.length);
}
}
if (socketSet.isSet(listener)) // connection request
{
Socket sn = null;
scope (failure)
{
writefln("Error accepting");
if (sn)
sn.close();
}
sn = listener.accept();
assert(sn.isAlive);
assert(listener.isAlive);
if (reads.length < MAX_CONNECTIONS)
{
writefln("Connection from %s established.", sn.remoteAddress().toString());
reads ~= sn;
writefln("\tTotal connections: %d", reads.length);
}
else
{
writefln("Rejected connection from %s; too many connections.", sn.remoteAddress().toString());
sn.close();
assert(!sn.isAlive);
assert(listener.isAlive);
}
}
socketSet.reset();
}
}