1. hello (serial)
/++
#1 of the "primitive networking servers series". A serial (non-concurrent)
TCP server that just greets any connections with "Hello, world!" before
closing them.
+/
module hello;
import std.socket : InternetAddress, Socket, TcpSocket, SocketOptionLevel, SocketOption;
import std.stdio : writefln;
enum port = 4444;
void main() {
TcpSocket listener = new TcpSocket;
listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1);
listener.bind(new InternetAddress(port));
listener.listen(10);
writefln!"Listening on %d."(port);
while (true) {
Socket client = listener.accept;
writefln!"Received connection from %s."(client.remoteAddress.toString);
client.send("Hello, world!\n");
client.close;
}
}
Server interaction
$ dmd -run hello.d
Listening on 4444.
Received connection from 127.0.0.1:43546.
Received connection from 127.0.0.1:43548.
Received connection from 127.0.0.1:43550.
Client interaction
$ # using nmap's ncat, rather than GNU's or OpenBSD's netcat
$ nc --recv-only localhost 4444
Hello, world!
$ nc --recv-only localhost 4444
Hello, world!
$ nc --recv-only localhost 4444
Hello, world!
sockets? binding? listening? what?
Beej's Guide to Network Programming is a great introduction to these concepts.
is that REUSEADDR stuff necessary?
The server will work without it, but you'll get an error like the following on server restarts:
std.socket.SocketOSException@std/socket.d(2825): Unable to bind socket: Address already in use
----------------
??:? @trusted void std.socket.Socket.bind(std.socket.Address) [0x55cbfd41dc28]
??:? _Dmain [0x55cbfd3f6a92]
This
StackOverflow Answer explains what's going on there.
can I connect to this server remotely?
Firewalls permitting, yes: the port-only constructor of
InternetAddress
binds to
ADDR_ANY
. If you want to only bind to localhost for these tutorial servers, you can bind to
new InternetAddress("127.0.0.1", port)
instead.
is this server fit for purpose?
For well-behaved peers... probably? It accepts a connection (blocks, can throw an exception), prints some information about it (can throw an exception), sends a string to it (may return an error code,
may block), and then closes it (infallibly).