I'm trying to use the libchan library to send messages between machines using a go channel-like transport.
From what I've gathered, the rough idea is this:
- You have a SPDY client that sends a serialized command object to an address over tcp. This command object contains a libchan channel called a
Pipe
that the response is sent through. - When the server receives an incoming connection, it waits for a command object. When it gets one, it sends a response through the
Pipe
contained in the object.
Here's my point of confusion. For a channel to persist between two machines, they'd have to share memory or atleast share an abstraction that connects the two of them. From my grokking of the libchan codebase, I have no idea how this could be possible.
Here's a snippet from the example in the repo:
// client
receiver, remoteSender := libchan.Pipe()
command := &RemoteCommand{
Cmd: os.Args[1],
Args: os.Args[2:],
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
StatusChan: remoteSender,
}
err = sender.Send(command)
if err != nil {
log.Fatal(err)
}
err = receiver.Receive(response)
if err != nil {
log.Fatal(err)
}
os.Exit(response.Status)
and the server:
// server
t := spdy.NewTransport(p)
go func() {
for {
receiver, err := t.WaitReceiveChannel()
if err != nil {
log.Print("receiver error")
log.Print(err)
break
}
log.Print("about to spawn receive proc")
go func() {
for {
command := &RemoteReceivedCommand{}
err := receiver.Receive(command)
returnResult := &CommandResponse{}
if res != nil {
if exiterr, ok := res.(*exec.ExitError); ok {
returnResult.Status = exiterr.Sys().
(syscall.WaitStatus).ExitStatus()
} else {
log.Print("res")
log.Print(res)
returnResult.Status = 10
}
}
err = command.StatusChan.Send(returnResult)
The point I'm trying to hone in is here:
libchan.Pipe()
According to the source, this returns a channel. One reference is kept on the client, and the other is sent to the server. This channel is then used to pipe values from the latter to the former. How does this actually work in practice?