SebaGeek Lectus non solum ad dormiendum factus est.

Netpal

In diesem Beispiel möchte ich zeigen, wie man einen simplen TCP Echo-Server schreibt mit Hilfe vom Baseserver aus Netpal. Bevor man das hier liest sollte man vieleicht einen Blick auf die Funktionsweise geworfen haben.

Einführung

Mit der Hilfe von der BaseServer-Struktur braucht man für einen kompletten TCP-Server nur drei Funktionen zu implementieren, die sämtliche Netzwerkevents behandeln. Diese Funktionen bekommen als Parameter meist den Client, durch den ein Event erzeugt wurde und dazu eine Clientliste, welche sie auch zurück geben müssen.

Als erstes müssen wir den Fall behandeln, dass ein Client sich zu uns verbinden will. Dazu akzeptieren wir die Verbindung mit accept() und fügen ihn zur Client-Liste hinzu:

FUN openClient: seq[client] -> seq[client]
DEF openClient(list) == client(socket, <>) :: list
                  WHERE
                      -- seiteneffektbehafteter aufruf
                      socket == EXEC(sockaccept() & (
                                    \\ sock. succeed(sock)))

Dann müssen wir uns um Daten vom Client kümmern. Wir bekommen vom BaseServer den Client, welcher uns etwas geschickt hat, die jeweiligen Daten als Denotation und die Client-Liste (incl. client). Wir schicken die Daten mit einem kleinen Kommentar zurück.

FUN procClient: client ** denotation ** seq[client] -> seq[client]
DEF procClient(client(csock, _), data, list) ==
        EXEC(socksendto(msg, csock);
             succeed(list))
        WHERE
            msg == "Du sagtest: " ++ data

Letztenendes müssen wir noch die Verbindung zum Client trennen können.

FUN closeClient: client ** seq[client] -> seq[client]
DEF closeClient(cli, list) ==
        EXEC(sockcloseto(socket(cli));
             succeed(newlist))
        WHERE
            newlist == removeClient(cli, list)

Nur noch in einen srvcore verpacken.

FUN echoserver: srvcore
DEF echoserver == srvcore(openClient, procClient, closeClient)
... und ausführen.
	e runServer("31415"!, echoserver)

Natürlich ist dieses kurze Beispiel ziemlich EXEC-Lastig, aber der eigentliche Spaß kommt ja auch erst, wenn man anfängt ordentlich Daten in procClient zu verarbeiten. ;)

π