The Lobster Den
Home to spelling errors, deprecated HTML and wholesome fun.
FORTH Echo Server Revisited
2015-12-29 03:32:00 UTC
GForth comes with a special library called unix/socket.fs
for dealing with TCP socket connections. Unfortunatly, there is (as far as I know) no formal documentation on using socket.fs
aside from reading the source code. If you’re a FORTH novice like me that isn’t much help.
The best thing I could find was an example TCP echo server on Rosetta Code. You can try it out for yourself by:
- Copy the code into a local file.
- Execute the file via
gforth FILENAME
- Connect to the echo server using telnet (
telnet localhost 12321
). - Send it messages via telnet, seperated by a carriage return.
I decided to factor down the code some more and add additional comments:
\ Pull in the library
include unix/socket.fs
\ Set some defaults
128 constant buffer-size
4 constant maximum-connections-allowed
: 3drop
drop drop drop ;
: read-the-buffer
2dup 2dup buffer-size read-socket nip
dup 0> ;
: print-the-data
." got: " 2dup type ;
: echo-back
rot write-socket ;
: (echo) ( sock buf-- sock buffer )
begin
read-the-buffer
while
print-the-data
echo-back
repeat
3drop ;
create buffer buffer-size allot
\ This is the main loop. It expects the TCP port number
\ to be on the stack when called (12321 in this case).
: echo-server ( port -- )
\ Call 'create-server', passing in the desired port
\ number on top of stack.
create-server
\ ^ Socket id is now on top of stack...
\ .. after that, set the socket ID to listen with a
\ max backlog of 4 connections.
dup maximum-connections-allowed listen
begin
\ This word will block the thread and listen to the socket.
dup accept-socket
cr ." Someone just connected to the socket! " cr
\ Push the buffer on the stack...
buffer
\ ...then grab the execution token for (echo)
['] (echo)
\ Execute the XT for `(echo)` and push the
\ exception onto the stack (or 0 if OK)
catch
cr ." Disconnected with status code " .
drop close-socket
again ;
12321 echo-server
Notes
- I accidentally discovered that GForth has a 2 second inactivity timeout on sockets by default?
- I would like to extend a special thanks to Reddit user
ALazyGhost
for helping me understand connection queuing.