Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: The REBOL async:// tutorial - take 1

From: petr:krenzelok:trz:cz at: 3-Mar-2004 17:58

Maarten Koopmans napsal(a): Hi, that stuff looks really excelent! Strange thing is, that even if the code looks pretty straightforward, I don't understand every detail of it, but that is what there are questions for :-)
> handler: func [port [port!] state [word! error!] /local tmp cmd] [ > if error? :state [print mold disarm state return true] > switch state [ > connect [ > ; do HTTP request > insert port {GET /fg/anen.jpg HTTP/1.0^M^JHost: >www.3dwallpaper.com^M^J^M^J} >
That one - raw tcp stream, right? I wonder if some kind of dialect (set of functions) could be produced to handle that ugly MJMJMJ and GET commands etc., as e.g. read/custom allows. Just a theoretical question, if it even would be worth it, nothing more
> false > ] > read [false] > write [false] > close [ > ; get data > data: copy port >
OK, so that one does not block right? And it is so just because we are inside handler function, which is being called once some event happens on port, so theoretically some data should be awaiting us. I just wonder it comes in 'close switch part. We get here once other side closed connection? So if I understand it correctly, we read it in parts, but 'read part does nothing, rebol is internally buffering data (how large data is rebol able to buffer easily that way?) and once other side closes connection, we can read it by copy (which will not block, even if no-wait was not used), and whole data is being read out of the port buffer at once? Well, I hope I am still on track :-)
>Now for a simple server: > >First we add a listening server port to the system/ports/wait-list, like: >
Why? Is that needed? Am I right thinking it is because of View? Once View starts, it adds event-port into wait-list and if we want to process all various events properly, we have to go via wait-list?
> either error? try [listen: open/no-wait tcp://:8000] [ > port: open async://localhost:8000 > port/awake: do handler >
Above code somehow escapes my understanding :-) So if we are not able to open listen port (because e.g. we are already listening), we open connection on localhost to that port? What is that good for?
> ] [ > listen/awake: func [l /local p] [ > print "Got connection." > p: first listen > remove find system/ports/wait-list listen > port: make port! [scheme: 'async sub-port: p] >
that is something I never understood. That is why I was not able to further more deeply adapt Sterling's proxy.r script. It contained way too much port subport and proxy (as a port :-) stuff for my brain to swallow :-) 'p is assigned first connected client. It does not contain any sub-port, yet it can communicate. IIRC someone said, that sub-port contains real communication port. But I don't understand the difference, even without sub-port, I am able to send data here and there and I can see it buffered in port/state. What is sub-port then?
> open port > port/awake: do handler > false > ] > insert tail system/ports/wait-list listen > port: none > ] >
so overall - it is clever - once first event happens on listening port, we remove it from wait-list, reassign handler and insert it back into wait-list. That sounds like nice constructor/init method in OOP :-)
>As you can see, its awake function convert the accepted port to an async >one and sets the handler. So what is the handler then? > > handler: [ use [ buffer ][ > > buffer: copy [] > > func [port [port!] state [word! error!] /local tmp cmd] [ > if error? :state [print mold disarm state return true] > switch state [ > connect [print "Connected." false] > read [ > append buffer copy port > while [tmp: find buffer newline] [ > cmd: copy/part buffer tmp > remove/part buffer next tmp > do-cmd cmd > ] > false > ] > write [false] > close [print "Peer closed connection." close port true] > ] > ] > ] > ] > >The first thing to notice is the fact that we use 'use to create a context >that returns a function! value. This function (and only this particluar >value) has access to its buffer. By doing the handler block in the server >part above, every accepted port gets a copy of theis function value with >its own "static" buffer space. A very simple but effective trick. >
cool! Thanks for your tutorial, very educative! -pekr-