The sockets concept is one way of performing interprocess communication (IPC). It enables programs on the same computer to seek each other out and talk to each other. But it doesn't stop there, sockets work also for programs running on a network (anywhere on the internet if you're so wired).
To use sockets for IPC you need to write and run server and client programs.
The server runs on your local computer and is under your control. The client processes can be
anywhere on the network (your own computer(s) as a special case) and are not necessarily of your
own making. A server listens on a port for clients wanting to make contact. For remote
clients to contact your server they need to know your computer name and the port number the
server is using. Popular examples with servers available on almost all computers are FTP
(port 20), TELNET
(port 23), FINGER
(port 79), TIME-OF-DAY
(port 13) and QUOTE
(port 17).
Your own server just picks a port number that happens to be not in use (for instance 3145).
Most sockets-based IPC works by sending strings back and forth between server and client using
some kind of published protocol. For your own use you just think something up that works.
Because you're using Forth, the protocol is the easy part--sending counted strings and using
EVALUATE
will work nicely.
In its easiest form, starting a server on your computer looks like this:
3145 myserver
Here 3145 is the port number your server listens to (more or less arbitrarily picked). "Myserver" is a Forth colon definition containing (probably) an endless loop. It checks if a client tries to make contact on port 3145 and then exchanges strings with this client according to some protocol of your own design (no rules I know off). Socket communication is bidirectional.
The client part is just as simple. Assuming the client runs also on your own computer you would start it like this:
S" //." 3145 myclient
or
S" frunobulax" 3145 myclient
assuming your computer is named "frunobulax". Any URL is okay as long as you also provide a valid
port number and your server is active there. Note that you can use the iForth word
hostname ( -- c-addr u )
to return your computer name.
If you have progressed this far you will learn more by downloading the socket related files above. The files extend iForth with the following socket wordset:
OPEN-SERVICE ( c-addr u port# -- socket ) example: S" frunobulax" 3145 OPEN-SERVICE ( -- 4 ) CREATE-SERVER ( port# -- lsocket ) example: 3145 CREATE-SERVER ( -- 16 ) LISTEN ( lsocket /queue -- ) example: 16 7 LISTEN ACCEPT-SOCKET ( lsocket -- socket ) example: 16 ACCEPT-SOCKET ( -- 3 ) READ-SOCKET ( socket c-addr maxlen -- c-addr size ) example: 3 PAD 125 READ-SOCKET ( -- 'pad 125 ) WRITE-SOCKET ( c-addr size socket -- ) example: PAD 128 3 WRITE-SOCKET CLOSE-SOCKET ( socket -- ) example: 3 CLOSE-SOCKET +CR ( c-addr1 u1 -- c-addr2 u2 ) appends a hard CR+LF pair to the text BLOCKING-MODE ( socket on/off -- ) put the socket in/out of blocking mode SET-SOCKET-TIMEOUT ( u -- ) set the global timeout (in ms) on reading sockets GET-SOCKET-TIMEOUT ( -- u ) get the global timeout (in ms) on reading sockets
A named pipe is a second way of performing interprocess communication (IPC). Programs on the same computer (Linux), or anywhere on the network or internet (only Windows NT 4.0 file systems allowed), can seek each other out and talk to each other. The difference with using sockets is that you don't need the rather arbitrary port number, just a specially formatted (equally arbitrary :-) file name. Also, I don't know of any publicly accessible named pipes on the internet. Like sockets, one writes Forth programs for the server and client ends, and IPC works by sending strings back and forth between server and client using a (published) protocol of your own design.
In its easiest form, starting a named pipe server on your computer looks like this:
S" //./pipe/forthserver" serverspeed ( Windows ) S" /dev/forthserver" serverspeed ( Linux )
Here the file name defines the path the clients take to your server (arbitrarily picked). Note the "/pipe" part of the path, this is required for Windows NT. "Serverspeed" is a Forth colon definition (probably) containing an endless loop. It checks if a client tries to make contact and then exchanges strings with this client according to some protocol of your own design. Named pipe communication is bidirectional.
The client part is just as simple. Assuming the client runs also on your own computer you would start it like this:
S" //./pipe/forthserver" clientspeed
or
S" //frunobulax/pipe/forthserver" clientspeed
or
S" /dev/forthserver" clientspeed
assuming your computer is named "frunobulax" (Linux doesn't support named pipes over the network).
If you have progressed this far you can learn more by downloading the named pipe related files above. The files extend iForth with the following named pipe wordset:
OPEN-NAMED-PIPE ( c-addr u timeout -- handle ) example: S" //frunobulax/pipe/clientspeed" 5000 OPEN-NAMED-PIPE ( -- 3 ) CREATE&ACCEPT ( c-addr u -- handle ) example: S" //frunobulax/pipe/serverspeed" CREATE&ACCEPT ( -- 3 ) READ-NAMED-PIPEX ( c-addr maxlen handle -- c-addr size ) example: PAD 125 3 READ-NAMED-PIPEX ( -- 'pad 125 ) WRITE-NAMED-PIPE ( c-addr size handle -- ) example: PAD 128 3 WRITE-NAMED-PIPE CLOSE-NAMED-PIPE ( handle -- ) example: 3 CLOSE-NAMED-PIPEYou may find that this wordset is a somewhat easier to understand than the socket wordset, although sockets are more versatile (can use any URL).
READ-FILE
WRITE-FILE
and
CLOSE-FILE
words. Because of Microsoftisms this doesn't work for Windows. Therefore iForth has
given the read/write/close actions new names, although it wouldn't be strictly necessary
for iForth Linux. The named pipe set doesn't support multiple clients connecting to a
single server (it looks like Windows NT 4.0 supports it, but I can't figure out how).
Note that current Windows documentation states that named pipe servers need better than Windows 2000 Server,
and named pipe clients need better than Windows 2000 Professional. I couldn't get the cliserv2.frt
example to work
on my current Windows XP Pro installations.
Benchmark 1: 20 Mbytes copied between two iForths on machine 1;
Benchmark 2: 20 Mbytes copied from an iForth on machine 2 to an iForth on machine 1.
Systems for sock test: Windows XP Pro, running on (1) an Intel PIV 3GHz/1GB and (2) an Intel
Core 2 Duo 2.66 GHz/2GB. The PC's were networked using motherboard Realtek
network adapters (100 Mbit/s).
Systems for npipe test: Windows NT 4.0, running on (1) an Intel Pentium 166MHz/48MB and (2)
an Intel Pentium 200MHz/48MB. The PC's were networked using cheap NE2000 clones (10 Mbit/s).
benchmark | process A read | process B write ===========+================+================ sock bm 1 | 72 MB/sec | 732 MB/sec sock bm 2 | 11.5 MB/sec | 2.857 GB/sec npipe bm 1 | 15 MB/sec | 15 MB/sec npipe bm 2 | 715 KB/sec | 715 KB/sec(The benchmarks were also done under Linux and performed even better there.)
As you can see, sockets look nice for processes on different machines, while named pipes are good for processes on the same machine. For Linux there should be almost no difference between sockets and named pipes.
I suggest using sockets for everything: portable, fast, and work across networks and operating systems.