[REBOL] Re: Problem: Talking from Rebol to Rebol via socket
From: petr::krenzelok::seznam::cz at: 22-Feb-2009 15:40
Robert M. Münch napsal(a):
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA384
>
> Hi, I made some small steps forward. At least I can send a message and get
> an answer. But only once, I want this to run in a loop on the server and th
> e client side. My actual code now is:
>
> === Server
> rebol []
>
> c-port: 12345
> listen: open/direct/no-wait join tcp://: c-port
>
> waitports: [listen]
>
> print "Listening:"
>
> ; wait until something happens
> connection: wait waitports
> if same? connection listen [
> print [tab "Connected"]
> c-client: first connection
>
> forever [
> print [tab "Read message from c-side"]
> print copy c-client
>
> print [tab "Send answer to c-side"]
> insert c-client "r-side"
> ]
> ]
>
> === Client
> rebol []
>
> connection: open/direct/no-wait tcp://localhost:12345
>
> forever [
> print "Sending to Rebol server"
> insert connection "r-side-client"
>
> print "Receiving from Rebol server"
> prin tab
> while [data: copy connection] [prin data]
> print newline
>
> ]
>
> === Problem
> The client side can only send once because it get stuck in the WHILE loop a
> lways getting some data from the server. The server loops, doesn't read any
> thing from the client and immediately sends out the next message to the cli
> ent.
>
> Is there a way that I can WAIT to "read a message" or "send a message"? I'm
> missing a way to control/react on the communication direction flow.
>
yes, there is. In async mode, you are responsible for "waiting for
signal" - you have to do handshaking yourself. As I said in my previous
email, be carefull, as you will run out from your data :-) So, look into
your server. You waint for first connection. Good. Then you get your
connection, enter forever loop, but you don't wait for the other side!
Copy is not blocking, so it copies from the OS buffer (direct mode), and
there is no data (empty string returned). Put wait c-client as first
means of forever loop. The mindset is more difficult with async mode,
and I sometimes too struggly a bit - where to wait, and where the wait
is not necessary.
Here's the mindset:
wait port ; or wait/all [port1 port2 0:00:01], whatever ...
while [not empty? data: copy port][append result data]
remember, that one call to 'copy just reads out what is available at the
given time. Sometimes ppl use copy/part, to read in some chunks. while
not empty? will ensure you read out everything available. But you don't
have to do that, as you can as well read it out "at next port visit" :-)
If you want to look how to read data from many ports, Sterling's proxy
script in rebol.org archive was always a good inspiration for me, as it
was able to open multiple connections, keep pairs of send/rcv ports
stored, etc.
Robert- here's my "multiserver" script I did for my friend some time
ago. He was doing some embedded stuff and wanted me to catch data from
devices, write them down to file, and log events. Not sure it will work
for you, as I now translated it into english, including variables.
Hopefully no bug there:
----------------------------
REBOL [
Title: "Multiserver"
Version: 0.2
Author: "Petr Krenzelok"
]
;--- open listen server in an async mode
listen-port: 9005
server: open/direct/no-wait/binary join tcp://: listen-port
print ["Server running on port: " listen-port]
;--- set-up a wait-list - rebol will wait for every item contained ...
wait-list: copy []
;--- set-up a block to store open connections in there ...
;--- along with info - remote IP, port ...
conn-list: copy []
;--- insert time and server into wait-list
insert wait-list 0.001
insert wait-list server
;--- forever= endless loop ....
forever [
event-port: wait wait-list
;--- if more events, let's pick first one (maybe not needed?)
if block? event-port [event-port: first event-port]
;--- has event happened on our listening server? (new connection request)
;--- if so, accept the connection, insert connection into wait-list
if event-port == server [
;--- accept connection ...
time: now/time/precise
connection: first server
print join "New connection from: " [connection/remote-ip ":"
connection/remote-port " at " time]
;--- append it into list of ports we wait for events (wait-list)
insert wait-list connection
;--- append into our internal register of connections and its
parameters
insert conn-list reduce [connection connection/remote-ip
connection/remote-port]
write/append join %data- reduce [connection/remote-ip "-"
connection/remote-port".txt"]
join "New connection from: " [
connection/remote-ip ":" connection/remote-port
" at " time
newline
"---------------------------------------------------------"
newline
]
;--- uncomment to see the data in console ...
;probe connection
]
;--- if event received is not new connection, it might be data on
already existing connection
if found? conn-port: find conn-list event-port [
;--- let's copy data ...
time: now/time/precise
data: copy event-port
;--- close request (none) or real data arriving?
either none? data [
print join "Closing connection request from: " [conn-port/2 ":"
conn-port/3 " at " time]
;--- Write close even request into file ...
write/append join %data- reduce [conn-port/2 "-" conn-port/3 ".txt"]
join newline [
"---------------------------------------------------------"
newline
"Closing connection request from: "
conn-port/2 ":" conn-port/3
" at " time
newline newline
"========================================================="
newline
newline
]
close event-port
remove/part conn-port 3
][
;--- if we are here, real data arrived ...
print join "Data from: " [conn-port/2 ":" conn-port/3 " at " time]
;--- write data into file ...
write/append join %data- reduce [conn-port/2 "-" conn-port/3
.txt
] to-string data
;--- uncomment to see data printed to console
;print mold to-string data
;print mold data ; data as binary, not string
] ;end 'either
] ;end 'if
] ;end 'forever