Hare by Example: TCP Server

TCP servers are also possible in Hare. The example shows a simple single connection handling server. In order to support multiple connections you'd need to set up event polling with the `unix::poll` module Hare offers to manage those connections as file descriptors.

use fmt;
use io;
use net;
use net::tcp;
use net::ip;
use os;
use strings;

export fn main() void = {
	// Create a tcp listener on the local v4 ip and a port
	const listener = tcp::listen(ip::LOCAL_V4, 9000)!;

	// Since we're writing a server we loop forever to wait for
	// incoming connections and data.
	for (true) {
		const conn = tcp::accept(listener)!;
		const peer = tcp::peeraddr(conn) as (ip::addr, u16);

		for (true) {
			// We define a buffer to hold incoming data
			let buf: [os::BUFSZ]u8 = [0...];

			const sz = match(io::read(conn, buf[..])!) {

			// Yield the size of the bytes read so we can
			// re-slice later on.
			case let sz: size =>
				yield sz;

			// If we get an EOF then we break to wait for
			// the next connection to come in.
			case io::EOF =>
				net::close(conn)!;
				break;
			};

			// Re-slice the buffer to the length of the data
			// that came in.
			let buf = buf[..sz];

			fmt::printfln("{}:{} says {}",
				ip::string(peer.0), peer.1,
				strings::fromutf8_unsafe(buf))!;

			// Echo it back to the client
			io::write(conn, buf)!;
		};
	};
};
# First, run the example to start the server
$ hare run tcp-server.ha
4/4 tasks completed (100%)
127.0.0.1:45524 says Hello TCP server! I am a TCP client!

# Second, connect to the server with netcat and send a message. The
# second message we get back has been echoed back to us.
$ nc 0.0.0.0 9000
Hello TCP server! I am a TCP client!
Hello TCP server! I am a TCP client!