Unix socket ports are block-buffered, so after writing to them you need to flush the output. Something like

  (write-json data port)
  (flush-output port)

Your code on github has calls to flush-output without the port argument. That doesn't flush the unix socket port; it flushes the current output port (usually the console or DrRacket) instead---and those ports are line-buffered anyway.

That's my best guess about the problem you saw.

BTW, even after that issue, I would worry about how Racket's IO system interacts with SOCK_SEQPACKET sockets. Specifically, I think you might lose data if a packet is larger than some internal buffer used by Racket. From "man socket":

  SOCK_SEQPACKET sockets employ the same system calls as
  SOCK_STREAM sockets. The only difference is that read(2) calls
  will return only the amount of data requested, and any data
  remaining in the arriving packet will be discarded.

Ryan


On 02/12/2016 01:24 PM, Ty Coghlan wrote:
As part of a course I'm in, we had to write a simple bridge simulation that 
could handle data messages to and from unix ports that have attached to them 
several hosts. In addition, these bridges have to implement a simple spanning 
tree algorithm, and send and receive BPDU messages. These messages are all 
formatted in JSON. My partner and I went about designing this in racket, 
changing the port protocol from SOCK_STREAM to SOCK_SEQPACKET (changing the 
binding of the variable from 1 to 5) in the unix library: 
https://github.com/racket/unix-socket.

We ran into the problem where we were able to read messages from the hosts 
attached to the unix sockets, however, we could not read messages that we had 
sent out (which through the simulation get bounced back to the bridge so we can 
set up the spanning tree). This lead us to believe that there is a bug in how 
we write data to the unix socket, and we spent so long debugging it that we 
eventually just rewrote the program in python to make in before the deadline.

All outgoing messages are written by a function called broadcast:

(define (broadcast source destination type message port)
   (write-json (hash 'source source 'destination destination
                     'type type 'message message)
               port))

It takes a string source, destination, message type, message, and finally an 
output port to write them on. Then it just wraps them up in a hash table and 
writes them to the port. We attempted to use display, print, regular write, and 
none of them alleviated the problem. We then looked at everything that passes 
data to broadcast, which includes the bpdu function

(define (bpdu bridge-id root-id cost-to-root lans)
   (for ([lan (hash-values lans)])
     (broadcast bridge-id "ffff" "bpdu"
                (jsexpr->string (hash 'id bridge-id 'root root-id 'cost 
cost-to-root))
                (cadr lan))))

bpdu takes in the current bridge-id, root-id, cost-to-root, and all lans (where 
lans are a three element list of lan id, out-port, and in-port), and simply 
formats them as a string before passing it as the message argument in broadcast 
to every port. This bpdu message is called from our main function, which sets 
up the unix socket connections and continuously loops, sending bpdus every 
500ms. The full (messy) file can be seen at 
https://github.com/cdris/bridges/blob/master/3700bridge.rkt.

Any help would be immensely appreciated.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to