TCP-SERVER
FOR GFORTH
This is the
page for a tcp-server written in the fabulous GForth programming language. It
is written as an exercise in Forth, as my first Forth-project, and as a
out-of-curiosity project about how low-level sockets are handled in BSD/Unix.
It is an alpha-release, but is has passed my non-scientific tests without
problems. Testing has been done through some perl-scripts which have been ran
on a bunch of clients simultaneously, but these scripts can certainly be
improved.
The server
can be used as a non-blocking single-threaded system or it can run in threaded
mode as well. The threaded version is based on my (limited?) understanding of
the tasker.fs-library in GForth, but it seems to work well.
The server
has been tested on Mac/Intel, Mini Mac with PPC, Linux Red Hat 8.0 and FreeBsd
6.3 with gforth (snapshop) version 0.6.9, all 32-bits cpuÕs. The server is
based on FFCall, for interfacing with glibc, it has been compiled without
problems for me, just configure, make, make test, and then make install.
The server
is based on BSD-sockets and it contains a library for handling bit-arrays. I
think the Windows version of the fd_set (without have done any deep
investigations) is based on a byte-array, so it will probably not run on
Windows, without rewriting the bit-array-file.
To use the
server:
include
tcpserver.fs
create_default_server_data
8888
open-socket-accept
This starts
the server with the default settings, port 8888. The word
create_default_server_data returns a struct, which look like this:
struct
cell% field sd_inbuffer
cell% field sd_outbuffer \ not
in use presently
cell% field sd_inbuffer_size
cell% field sd_outbuffer_size
cell% field
sd_received_data_length
cell% field sd_client_data
cell% field sd_time_struct
cell% field sd_callback_response
cell% field sd_callback_accept
end-struct
server-data
The default
in-buffer is small, only 100 bytes, allocate larger room and change the struct
if needed. The struct contains the pointer to the buffer.
After data
is received the data is located at the address of the sd_inbuffer, the length
is in sd_receifed_data_length.
Callbacks
are normal forth words. The connection words should defined like this:
:
socket-accepted ( fid sd -- )
multi-server
{ fd }
." Socket accepted on port: "
. cr
." Connection from: " fd
sd_client_data @ sin_addr @ hex . decimal cr
;
The word
multi-server can be omitted, it a single threaded version of the server is
wanted. The word PAUSE is needed to change focus to another thread.
Callback
for response to client is something like send-socket-line (this is the default
word to be overritten). This word read input from the inbuffer, and sends a
reply back to the client.
:
send-socket-line ( fid sd -- )
multi-server
{
sd }
sd
sd_inbuffer @ sd sd_received_data_length @ type
dup
s\" Hello Major Tom. Are you receiving?\n" 0 send_socket
dup
0< if abort" Could not send line" endif
2drop
;
Callbacks are set the default Forth way:
Ô my-word
server-data-struct sd_callback_response !
If the
server shall close the connection, this can be done with the word
Close-the-socket
( fid -- )
Client side
closing is handled by the server.
Mutable
data: The data in
the sd-struct is very mutable and it will for sure change after using the
threading-word pause. The reason is that all connections are sharing the same
sd-struct, if data from this is needed after a thread-switch it should be
copied to a new, local struct ahead of the pause-word.
Versions:
0.1 -
Contains basic functionality only.
Improvements:
- The word
send_socket should handle data which is longer than the buffer
- Currently
the server is based upon this pattern:
Client
opens connection
Server
responds and receives data
Client
receives and close connection
More
advanced patterns like for example receive-send-receive-send will be
implemented using sleeping threads in next version.
Bugs:
Well, this
is done on a computerÉ
The
code:
Download
from: http://egesund.org/forth/tcpserver.zip
There are
only two small files, after all this is Forth J
Comments
and code improvements are appreciated!
Petter
Egesund
petter
kr¿llalpha egesund.org