ZetCode

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.

fetch.a68
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.

split.a68
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.

status.a68
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.

refused.a68
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.

ping.a68
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

The Algol 68 Genie project

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

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Algol 68 tutorials.