Algol 68 TCP/IP sockets
last modified November 13, 2026
A TCP connection is a stream of bytes between two programs. Algol 68 Genie adds
one procedure for it: tcp request connects to a host and a port,
sends a request, reads everything the server sends back, and closes the
connection. It is an extension of the implementation, not part of the Revised
Report, and it is a client procedure: a program that uses it talks to a server
but does not become one.
This article builds a client that fetches a page, separates the headers from the body, reads the status code, copes with a refused connection, and speaks a small protocol of its own.
A test server
The examples connect to a server on the local machine, so the transcripts are
the same for every reader. Any server that answers with the expected text
works; the replies below were produced with netcat, which sends a
fixed response and closes the connection after the client stops writing. One
line in a second terminal is enough:
$ printf 'HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 16\r\n\r\nhello from server' | nc -l -p 8099
The -l option makes nc listen, and -p
gives the port. The server handles one connection and then ends, so it is
started again before each example. The text between the quotes is a complete
HTTP response: a status line, two header lines, an empty line, and a body of
sixteen characters.
A first request
tcp request takes four arguments: a REF STRING that
receives the reply, the host name or address, the request, and the port. It
returns 0 when the exchange succeeded and a non-zero code otherwise.
PROC without = (STRING s, CHAR c) STRING:
(
STRING out := "";
FOR i TO UPB s DO
IF s[i] /= c THEN out := out + s[i] FI
OD;
out
);
BEGIN
CHAR cr = REPR 13, nl = REPR 10;
STRING eol = cr + nl;
STRING request = "GET / HTTP/1.0" + eol + "Host: localhost" + eol + eol;
STRING reply;
INT rc = tcp request(reply, "127.0.0.1", request, 8099);
print(("return code ", whole(rc, 0), newline));
print((without(reply, REPR 13), newline))
END
The request is an HTTP GET followed by a blank line, which tells the server
that the request is complete. HTTP separates its lines with a carriage return
and a line feed, and Algol 68 has no escape for either, so the program builds
them from REPR 13 and REPR 10. The reply uses the same
pair, and the without procedure removes the carriage returns so
that the transcript shows plain lines.
The return code and the whole reply are printed. The empty line after the headers is part of the reply, and the body follows it.
$ a68g fetch.a68 return code 0 HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 16 hello from server
Headers and body
A response keeps its headers and its body apart with an empty line. Searching for two newline characters gives the position of that separator, and the two slices around it are the header block and the body.
PROC without = (STRING s, CHAR c) STRING:
(
STRING out := "";
FOR i TO UPB s DO
IF s[i] /= c THEN out := out + s[i] FI
OD;
out
);
BEGIN
CHAR cr = REPR 13, nl = REPR 10;
STRING eol = cr + nl;
STRING request = "GET / HTTP/1.0" + eol + "Host: localhost" + eol + eol;
STRING reply;
INT rc = tcp request(reply, "127.0.0.1", request, 8099);
reply := without(reply, REPR 13);
INT b, e;
IF grep in string(nl + nl, reply, b, e) = 0 THEN
print(("headers:", newline));
print((reply[1:b - 1], newline));
print(("body: ", reply[e + 1:], newline))
ELSE
print(("the reply has no body", newline))
FI
END
The header block ends one character before the first newline of the pair, and the body starts one character after the second. The program prints the headers under a label and the body in brackets, which shows that the body begins immediately after the empty line.
$ a68g split.a68 headers: HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 16 body: hello from server
The status line
The first line of an HTTP reply holds the protocol version and a three digit status code. A regular expression anchored at the start of the reply matches that line without the program having to split the text first.
BEGIN
CHAR cr = REPR 13, nl = REPR 10;
STRING eol = cr + nl;
STRING request = "GET / HTTP/1.0" + eol + "Host: localhost" + eol + eol;
STRING reply;
INT rc = tcp request(reply, "127.0.0.1", request, 8099);
INT b, e;
IF grep in string("^HTTP/[0-9.]+ [0-9]{3}", reply, b, e) = 0 THEN
print(("status code ", reply[e - 2:e], newline))
ELSE
print(("no status line", newline))
FI
END
The pattern matches the protocol, a space, and exactly three digits. The match ends at the last digit, so the slice of its final three characters is the code itself, and the program can compare it with 200 or with any other value.
$ a68g status.a68 status code 200
A refused connection
A port with no server behind it produces an error rather than a reply. The procedure returns a non-zero code, which is the error number of the operating system, and the reply string stays empty. A program must test the code before it uses the reply.
BEGIN
CHAR nl = REPR 10;
STRING reply;
INT rc = tcp request(reply, "127.0.0.1", "PING" + nl, 8098);
IF rc = 0 THEN
print(("connected, reply: ", reply, newline))
ELSE
print(("could not connect, code ", whole(rc, 0), newline));
print(("reply length ", whole(UPB reply, 0), newline))
FI
END
The code 111 is ECONNREFUSED, the error that the kernel reports
when nothing listens on the port. The reply has no characters at all, so the
length check and the code check agree, and the program prints a message instead
of a reply.
$ a68g refused.a68 could not connect, code 111 reply length 0
A protocol of your own
tcp request is not tied to HTTP. Any request and any reply are
strings of bytes, so a program can speak a protocol of its own with the same
call. The example sends a single word and expects an answer that ends with a
newline.
BEGIN
CHAR nl = REPR 10;
STRING reply;
INT rc = tcp request(reply, "127.0.0.1", "PING" + nl, 8097);
IF rc = 0 AND UPB reply > 0 THEN
print(("the server answered: ", reply[1:UPB reply - 1], newline))
ELSE
print(("no answer, code ", whole(rc, 0), newline))
FI
END
The reply is checked for content before it is sliced, because the last
character is dropped on the assumption that it is a newline. The server that
produced the transcript was started with
printf 'PONG from the test server\n' | nc -l -p 8097.
$ a68g ping.a68 the server answered: PONG from the test server
What the procedure does
tcp request performs the whole exchange in one call. It resolves
the host name, connects to the port, writes the request, reads until the server
closes the connection, and returns everything it received in one string. There
is no separate connect, send, or receive step, and no way to read part of a
reply and decide what to send next.
The procedure has no listening side and no timeout parameter. A server that keeps the connection open without sending anything leaves the program waiting, and a reply larger than the available memory cannot be handled. For a small client that fetches a page or asks a service a question, the single call is enough, and the string it returns can be examined with the procedures of the regular expressions article.
Next steps
The regular expressions article explains the patterns that parse a reply, and the command-line arguments article explains how a script receives the host and the port from its caller. The strings article covers the slicing and concatenation that build a request, and the files article stores a reply on disk.
Source
Revised Report on the Algorithmic Language Algol 68
In this article we have connected to a local server with
tcp request, built an HTTP request from strings and
REPR, printed the reply, separated the headers from the body, read
the status code with a pattern, handled a refused connection, and spoken a
protocol of our own.
Author
List all Algol 68 tutorials.