Changes between Version 13 and Version 14 of DatagramChannelsCowan


Ignore:
Timestamp:
10/30/13 21:08:34 (4 years ago)
Author:
cowan
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatagramChannelsCowan

    v13 v14  
    2929`(datagram-channel-receive-from `''channel''` `''bytevector''` `[''start'' [''end'']]`)` 
    3030 
    31 Receives a datagram from ''channel'' into the portion of ''bytevector'' defined by ''start'' (inclusive) and ''end'' (exclusive).  If ''end'' is omitted, it is the length of ''bytevector'' plus one; if ''start'' is omitted, it is 0.  Returns two values: the sending endpoint and `#t` if the datagram was complete or `#f` if it was truncated. It is an error to invoke this procedure on an output-only datagram channel.  In Posix terms this is `recvfrom()`. 
     31Receives a datagram from ''channel'' into the portion of ''bytevector'' defined by ''start'' (inclusive) and ''end'' (exclusive).  If ''end'' is omitted, it is the length of ''bytevector'' plus one; if ''start'' is omitted, it is 0.  Returns two values: the sending endpoint and the number of bytes received, which may be greater than, equal to, or less than ''end - start''.  If it is greater, excess bytes in the datagram are discarded; if it is less, the remaining bytes of the bytevector are unchanged. It is an error to invoke this procedure on an output-only datagram channel.  In Posix terms this is `recvfrom()`. 
    3232 
    3333`(datagram-channel-connect! `''channel''` `''endpoint''`)` 
     
    5353== Example: TFTP == 
    5454 
    55 TFTP is a simple UDP-based protocol documented in RFC 1350.  For our purposes, all that matters is that the client sends the first datagram and the server sends exactly one response to each datagram (assuming no loss of packets in transmission). 
     55TFTP is a simple UDP-based protocol documented in [http://tools.ietf.org/rfc/rfc1350.txt RFC 1350].  For our purposes, all that matters is that the client sends the first datagram and the server sends exactly one response to each datagram (assuming no loss of packets in transmission). 
    5656 
    57 The server uses `(make-datagram-channel (make-network-endpoint 69))` to create a datagram channel listening on the local UDP port 69 and then uses `(datagram-channel-receive-from `''chan''` `''bytevector''`)` to obtain an initial datagram.  The server then calls `(make-datagram-channel)` to create a new datagram channel listening on a randomly chosen port.  This datagram channel is then connected with `(datagram-channel-connect! `''client-host''` `''client-port''`)` to the client's host and port, and the response to the initial datagram is sent on the new channel.  All further transactions with that client are performed over the newly created channel. 
     57Here is skeleton code for a read-only server: 
    5858 
    59 The client starts by using `(make-datagram-channel)` and then `(datagram-channel-connect! `''chan''` (make-network-endpoint `''host''` 69))` to connect to the server.  The initial datagram is sent with `(datagram-channel-send `''bytevector''`)`.  When the server replies, the channel is reconnected with `(datagram-channel-connect! (make-network-endpoint `''host''` `''server-port''`))` and the remaining datagrams are sent over the channel. 
     59{{{ 
     60(define server-chan (make-datagram-channel (make-network-endpoint 69))) 
     61 
     62(define buffer (make-bytevector 512) 
     63 
     64(define (tftp-server) 
     65  (let file-loop () 
     66    (let-values (((endpoint size) 
     67                 (datagram-channel-receive-from tftp-chan buffer)) 
     68      (define file (open-input-file (extract-filename buffer 0 size))) 
     69      (define chan (make-datagram-channel)) 
     70      (datagram-channel-connect! chan endpoint) 
     71      (let block-loop ((seq 1)) 
     72        (define raw-block-length (read-bytevector! file buffer)) 
     73        (define block-length 
     74          (if (eof-object? raw-block-length) 0 raw-block-length)) 
     75        (datagram-channel-send chan (box-tftp-data buffer 0 block-length seq)) 
     76        (let-values (((endpoint acksize) 
     77                     (datagram-channel-receive-from chan buffer))) 
     78          (validate-ack! buffer 0 acksize) 
     79          (if (= size 512) (block-loop (+ 1 seq))) 
     80          (datagram-channel-close chan) 
     81          (close-input-port file) 
     82          (file-loop))))) 
     83}}} 
     84 
     85And here is skeleton code for a corresponding client: 
     86 
     87{{{ 
     88(define (tftp-client hostname filename) 
     89  (define chan (make-datagram-channel)) 
     90  (define file (open-output-file filename)) 
     91  (define buffer (make-bytevector 512)) 
     92  (datagram-channel-connect! chan (make-network-endpoint host 69)) 
     93  (datagram-channel-send chan (format-read-request file)) 
     94 
     95  (let block-loop ((seq 1)) 
     96    (let-values (((endpoint size) 
     97                 (datagram-channel-receive-from chan buffer))) 
     98      (write-bytevector file (unbox-tftp-data buffer 0 size)) 
     99      (if (= size 512) (block-loop (+ seq 1))))) 
     100  (datagram-channel-close chan) 
     101  (close-output-port file)) 
     102}}} 
    60103 
    61104== Issues ==