Listener process
[1/13] from: atruter::labyrinth::net::au at: 3-Sep-2003 10:48
Any ideas on what the simplest way to implement a local listener process in
REBOL would be? I want to have an [encapped] script that can be started and
then "listens" for incoming requests from other [REBOL] scripts and passes
results back. I could certainly do this via files, but is there a nifty way
of doing it in-memory?
If the answer to this question is simply, "Look at Rugby / Async", then
that alone is worth knowing. ;)
Regards,
Ashley
[2/13] from: rebol:techscribe at: 2-Sep-2003 18:04
Hi Ashley.
Ports are probably the way to go. You will be able to see an example in
ion.r in ion.pe release 1.1. I haven't had the time to look at ruby, so
I don't know if that would be a good example.
Elan
Ashley Truter wrote:
[3/13] from: andreas:bolka:gmx at: 3-Sep-2003 3:14
Wednesday, September 3, 2003, 2:48:07 AM, Ashley wrote:
> If the answer to this question is simply, "Look at Rugby / Async", then
> that alone is worth knowing. ;)
look at rugby or the storm engine :)
--
Best regards,
Andreas
[4/13] from: brett:codeconscious at: 3-Sep-2003 11:34
When I last looked at Rugby it allowed you to do the tcp/ip route in
minutes. Maarten is doing more work in this area, but I don't know what
stage he has achieved.
It could be nice to have some local memory pipeline/mailbox scheme in REBOL.
With library access maybe someone could cook one up and give it to RT to
include in future :^)
Tcp/ip port are probably easier to get going though :)
Check that the OS you are going to use this on will support the throughput
you need. (Eg. you may/may not have an issue in win95/98).
Regards,
Brett.
[5/13] from: greggirwin:mindspring at: 2-Sep-2003 20:33
Hi Ashley,
AT> Any ideas on what the simplest way to implement a local listener process in
AT> REBOL would be? I want to have an [encapped] script that can be started and
AT> then "listens" for incoming requests from other [REBOL] scripts and passes
AT> results back. I could certainly do this via files, but is there a nifty way
AT> of doing it in-memory?
AT> If the answer to this question is simply, "Look at Rugby / Async", then
AT> that alone is worth knowing. ;)
It isn't hard to create a process that listens on a port and
returns data to clients when they connect, but Rugby is a brilliant
absolute-no-brainer if you want to serve up functions for remote
execution. Of course, that means including it in your code, but it's
really terrific stuff.
I'd say try Rugby first. If you decide not to use it, for whatever
reason, you won't have wasted much time, and maybe gained some good
insight in the process.
-- Gregg
[6/13] from: greggirwin:mindspring at: 2-Sep-2003 20:35
Hi Ashley,
P.S. If you decide to do it yourself, I (or others) can provide some
boilerplate to get you going.
-- Gregg
[7/13] from: atruter:labyrinth:au at: 3-Sep-2003 13:44
Hi Gregg,
> P.S. If you decide to do it yourself, I (or others) can provide some
> boilerplate to get you going.
That would be much appreciated, as I am only interested in pretty basic
stuff at the moment (more command / response orientated than code passing,
not worrying about multiple callers). The following code snippets
illustrate (hopefully!) what I'm trying to achieve.
; Listener script
...
forever [
cmd: get-cmd
result: switch/default cmd [
0 [quit]
1 ["one"]
2 ["two"]
][
none
]
send-result result
]
...
; Calling script
...
result: send-cmd 1
if not none? result [print result]
...
Regards,
Ashley
[8/13] from: maarten:vrijheid at: 3-Sep-2003 9:08
Ashley,
Try Rugby, I'm sure that will work in your case.
http://www.koopgoedkoop.net/rugby.zip
or the async beta at
http://www.koopgoedkoop.net/software/rugbyb1.zip
--Maarten
[9/13] from: greggirwin:mindspring at: 3-Sep-2003 18:03
Hi Ashley,
AT> I am only interested in pretty basic stuff at the moment (more
AT> command / response orientated than code passing, not worrying
AT> about multiple callers).
Here's the basic idea:
;; Server ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
REBOL []
listen-port-num: 2003
process-client-request: func [port /local cmd][
if error? set/any 'err try [
wait port
cmd: copy port ; get cmd
print [now/time/precise tab "client request:" cmd]
result: switch/default load cmd [
0 [quit]
1 ["one"]
2 ["two"]
][none]
insert port result ; send result
close port ; service only one request
][print mold disarm err]
]
; Open our main port that listens for client connections.
if error? set/any 'err try [
server-port: open/no-wait join tcp://: listen-port-num
][
print ["Error opening listen port:" mold disarm err]
halt
]
print "Simple Server Now Listening..."
forever [
process-client-request first wait reduce [server-port]
;-- The longer version
;wake-port: wait reduce [server-port]
;if wake-port = server-port [
; process-client-request first wake-port
;]
]
;; Client ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
REBOL []
print "Simple Client"
server-port: 2003
forever [
wait 2
port: open join tcp://127.0.0.1: server-port
insert port first random [1 2]
wait port
print copy port
close port
]
If you want to handle multiple requests from a client, without them
opening the port each time, you'll have to do things a little
differently, but hopefully this will get you started.
-- Gregg
[10/13] from: atruter:labyrinth:au at: 4-Sep-2003 10:50
Thanks Gregg,
Works a treat! Now I've got something to experiment with before tackling
[no pun intended] Rugby. ;)
Regards,
Ashley
[11/13] from: brett:codeconscious at: 4-Sep-2003 11:59
Ashley,
> Works a treat! Now I've got something to experiment with before tackling
> [no pun intended] Rugby. ;)
I forgot to mention earlier there are two tiny scripts in this article that
use Rugby:
http://www.codeconscious.com/rebol/articles/introducing-rugby.html
Regards,
Brett.
[12/13] from: g:santilli:tiscalinet:it at: 4-Sep-2003 10:21
Hi Gregg,
On Thursday, September 4, 2003, 2:03:28 AM, you wrote:
GI> Here's the basic idea:
Another way to pass the data around:
send-message:
func [port message /only /local res]
[ message: mold/all message
insert insert insert port length? message " " message
if not only
[ if object? res: get-message/only port
[ make error! next next second res]
] ]
buffer: none
get-message:
func [port /only /local pos len message err localbuff]
[ either error? err: try
[ if not string? buffer [buffer: clear ""]
localbuff: make string! 65536
while [not found? pos: find buffer " "]
[ wait port
read-io port localbuff 65534
insert tail buffer localbuff
clear localbuff
]
if integer? len: attempt [to integer! copy/part buffer pos]
[ buffer: next pos
while [len > length? buffer]
[ wait port
read-io port localbuff 65534
insert tail buffer localbuff
clear localbuff
]
message: buffer
buffer: copy skip buffer len
clear skip message len
message: load message
] ]
[ if not only [send-message/only port disarm err]
err
]
[ if not only [send-message/only port 'OK]
message
] ]
They expect the port to be /BINARY. (I'm using READ-IO so /NO-WAIT
shouldn't be necessary. I'm not using COPY because while trying to
find out why it crashed sometimes I tried switching from COPY to
READ-IO and then left it like that. The crash was due to LOAD.)
You can use them to send and receive across a port any REBOL
value. They are blocking, so you just send-message on one side and
get-message on the other side. Use the Storm engine if you need
anything better. :)
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[13/13] from: greggirwin:mindspring at: 4-Sep-2003 8:14
GS> Another way to pass the data around:
Excellent Gabriele!
-- Gregg