Permalink
114 lines (96 sloc) 3.4 KB
/*
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();
}
}