110 lines
3.9 KiB
D
110 lines
3.9 KiB
D
import std.stdio, std.socket, std.array;
|
|
|
|
void main() {
|
|
enum ushort port = 7;
|
|
enum int backlog = 10;
|
|
enum int max_connections = 60;
|
|
enum BUFFER_SIZE = 16;
|
|
|
|
auto listener = new TcpSocket;
|
|
assert(listener.isAlive);
|
|
listener.bind(new InternetAddress(port));
|
|
listener.listen(backlog);
|
|
debug writeln("Listening on port ", port);
|
|
|
|
// Room for listener.
|
|
auto sset = new SocketSet(max_connections + 1);
|
|
|
|
Socket[] sockets;
|
|
char[BUFFER_SIZE] buf;
|
|
|
|
for (;; sset.reset()) {
|
|
sset.add(listener);
|
|
foreach (each; sockets)
|
|
sset.add(each);
|
|
|
|
// Update socket set with only those sockets that have data
|
|
// avaliable for reading. Options are for read, write,
|
|
// and error.
|
|
Socket.select(sset, null, null);
|
|
|
|
// Read the data from each socket remaining, and handle
|
|
// the request.
|
|
for (int i = 0; ; i++) {
|
|
NEXT:
|
|
if (i == sockets.length)
|
|
break;
|
|
if (sset.isSet(sockets[i])) {
|
|
int read = sockets[i].receive(buf);
|
|
if (Socket.ERROR == read) {
|
|
debug writeln("Connection error.");
|
|
goto SOCK_DOWN;
|
|
} else if (read == 0) {
|
|
debug {
|
|
try {
|
|
// If the connection closed due to an
|
|
// error, remoteAddress() could fail.
|
|
writefln("Connection from %s closed.",
|
|
sockets[i].remoteAddress()
|
|
.toString());
|
|
} catch (SocketException) {
|
|
writeln("Connection closed.");
|
|
}
|
|
}
|
|
SOCK_DOWN:
|
|
sockets[i].close(); //Release socket resources now.
|
|
|
|
// Remove from socket from sockets, and id from
|
|
// threads.
|
|
if (i != sockets.length - 1)
|
|
sockets[i] = sockets.back;
|
|
sockets.length--;
|
|
debug writeln("\tTotal connections: ",
|
|
sockets.length);
|
|
goto NEXT; // -i- is still the NEXT index.
|
|
} else {
|
|
debug
|
|
writefln("Received %d bytes from %s:"
|
|
~ "\n-----\n%s\n-----",
|
|
read,
|
|
sockets[i].remoteAddress().toString(),
|
|
buf[0 .. read]);
|
|
|
|
// Echo what was sent.
|
|
sockets[i].send(buf[0 .. read]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Connection request.
|
|
if (sset.isSet(listener)) {
|
|
Socket sn;
|
|
try {
|
|
if (sockets.length < max_connections) {
|
|
sn = listener.accept();
|
|
debug writefln("Connection from %s established.",
|
|
sn.remoteAddress().toString());
|
|
assert(sn.isAlive);
|
|
assert(listener.isAlive);
|
|
sockets ~= sn;
|
|
debug writefln("\tTotal connections: %d",
|
|
sockets.length);
|
|
} else {
|
|
sn = listener.accept();
|
|
debug writefln("Rejected connection from %s;"
|
|
~ " too many connections.",
|
|
sn.remoteAddress().toString());
|
|
assert(sn.isAlive);
|
|
sn.close();
|
|
assert(!sn.isAlive);
|
|
assert(listener.isAlive);
|
|
}
|
|
} catch (Exception e) {
|
|
debug writefln("Error accepting: %s", e.toString());
|
|
if (sn)
|
|
sn.close();
|
|
}
|
|
}
|
|
}
|
|
}
|