262 lines
6.7 KiB
Markdown
262 lines
6.7 KiB
Markdown
# goczmq [![Build Status](https://travis-ci.org/zeromq/goczmq.svg?branch=master)](https://travis-ci.org/zeromq/goczmq) [![Doc Status](https://godoc.org/github.com/zeromq/goczmq?status.png)](https://godoc.org/github.com/zeromq/goczmq)
|
|
|
|
## Introduction
|
|
A golang interface to the [CZMQ v4.2](http://czmq.zeromq.org) API.
|
|
|
|
## Install
|
|
### Dependencies
|
|
* [libsodium](https://github.com/jedisct1/libsodium)
|
|
* [libzmq](https://github.com/zeromq/libzmq)
|
|
* [czmq](https://github.com/zeromq/czmq)
|
|
|
|
### For CZMQ master
|
|
```
|
|
go get github.com/zeromq/goczmq
|
|
```
|
|
#### A Note on Build Tags
|
|
The CZMQ library includes experimental classes that are not built by default, but can be built
|
|
by passing `--enable-drafts` to configure. Support for these draft classes are being added
|
|
to goczmq. To build these features against a CZMQ that has been compiled with `--enable-drafts`,
|
|
use `go build -tags draft`.
|
|
|
|
### For CMZQ = 4.0
|
|
```
|
|
go get gopkg.in/zeromq/goczmq.v4
|
|
```
|
|
### For CZMQ Before 4.0
|
|
```
|
|
go get gopkg.in/zeromq/goczmq.v1
|
|
```
|
|
## Usage
|
|
### Direct CZMQ Sock API
|
|
#### Example
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/zeromq/goczmq"
|
|
)
|
|
|
|
func main() {
|
|
// Create a router socket and bind it to port 5555.
|
|
router, err := goczmq.NewRouter("tcp://*:5555")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer router.Destroy()
|
|
|
|
log.Println("router created and bound")
|
|
|
|
// Create a dealer socket and connect it to the router.
|
|
dealer, err := goczmq.NewDealer("tcp://127.0.0.1:5555")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer dealer.Destroy()
|
|
|
|
log.Println("dealer created and connected")
|
|
|
|
// Send a 'Hello' message from the dealer to the router.
|
|
// Here we send it as a frame ([]byte), with a FlagNone
|
|
// flag to indicate there are no more frames following.
|
|
err = dealer.SendFrame([]byte("Hello"), goczmq.FlagNone)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Println("dealer sent 'Hello'")
|
|
|
|
// Receve the message. Here we call RecvMessage, which
|
|
// will return the message as a slice of frames ([][]byte).
|
|
// Since this is a router socket that support async
|
|
// request / reply, the first frame of the message will
|
|
// be the routing frame.
|
|
request, err := router.RecvMessage()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("router received '%s' from '%v'", request[1], request[0])
|
|
|
|
// Send a reply. First we send the routing frame, which
|
|
// lets the dealer know which client to send the message.
|
|
// The FlagMore flag tells the router there will be more
|
|
// frames in this message.
|
|
err = router.SendFrame(request[0], goczmq.FlagMore)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("router sent 'World'")
|
|
|
|
// Next send the reply. The FlagNone flag tells the router
|
|
// that this is the last frame of the message.
|
|
err = router.SendFrame([]byte("World"), goczmq.FlagNone)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Receive the reply.
|
|
reply, err := dealer.RecvMessage()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("dealer received '%s'", string(reply[0]))
|
|
}
|
|
```
|
|
#### Output
|
|
```
|
|
2015/05/26 21:52:52 router created and bound
|
|
2015/05/26 21:52:52 dealer created and connected
|
|
2015/05/26 21:52:52 dealer sent 'Hello'
|
|
2015/05/26 21:52:52 router received 'Hello' from '[0 103 84 189 175]'
|
|
2015/05/26 21:52:52 router sent 'World'
|
|
2015/05/26 21:52:52 dealer received 'World'
|
|
```
|
|
### io.ReadWriter support
|
|
#### Example
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/zeromq/goczmq"
|
|
)
|
|
|
|
func main() {
|
|
// Create a router socket and bind it to port 5555.
|
|
router, err := goczmq.NewRouter("tcp://*:5555")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer router.Destroy()
|
|
|
|
log.Println("router created and bound")
|
|
|
|
// Create a dealer socket and connect it to the router.
|
|
dealer, err := goczmq.NewDealer("tcp://127.0.0.1:5555")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer dealer.Destroy()
|
|
|
|
log.Println("dealer created and connected")
|
|
|
|
// Send a 'Hello' message from the dealer to the router,
|
|
// using the io.Write interface
|
|
n, err := dealer.Write([]byte("Hello"))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("dealer sent %d byte message 'Hello'\n", n)
|
|
|
|
// Make a byte slice and pass it to the router
|
|
// Read interface. When using the ReadWriter
|
|
// interface with a router socket, the router
|
|
// caches the routing frames internally in a
|
|
// FIFO and uses them transparently when
|
|
// sending replies.
|
|
buf := make([]byte, 16386)
|
|
|
|
n, err = router.Read(buf)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("router received '%s'\n", buf[:n])
|
|
|
|
// Send a reply.
|
|
n, err = router.Write([]byte("World"))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("router sent %d byte message 'World'\n", n)
|
|
|
|
// Receive the reply, reusing the previous buffer.
|
|
n, err = dealer.Read(buf)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("dealer received '%s'", string(buf[:n]))
|
|
}
|
|
```
|
|
#### Output
|
|
```
|
|
2015/05/26 21:54:10 router created and bound
|
|
2015/05/26 21:54:10 dealer created and connected
|
|
2015/05/26 21:54:10 dealer sent 5 byte message 'Hello'
|
|
2015/05/26 21:54:10 router received 'Hello'
|
|
2015/05/26 21:54:10 router sent 5 byte message 'World'
|
|
2015/05/26 21:54:10 dealer received 'World'
|
|
```
|
|
### Thread safe channel interface
|
|
#### Example
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/zeromq/goczmq"
|
|
)
|
|
|
|
func main() {
|
|
// Create a router channeler and bind it to port 5555.
|
|
// A channeler provides a thread safe channel interface
|
|
// to a *Sock
|
|
router := goczmq.NewRouterChanneler("tcp://*:5555")
|
|
defer router.Destroy()
|
|
|
|
log.Println("router created and bound")
|
|
|
|
// Create a dealer channeler and connect it to the router.
|
|
dealer := goczmq.NewDealerChanneler("tcp://127.0.0.1:5555")
|
|
defer dealer.Destroy()
|
|
|
|
log.Println("dealer created and connected")
|
|
|
|
// Send a 'Hello' message from the dealer to the router.
|
|
dealer.SendChan <- [][]byte{[]byte("Hello")}
|
|
log.Println("dealer sent 'Hello'")
|
|
|
|
// Receve the message as a [][]byte. Since this is
|
|
// a router, the first frame of the message wil
|
|
// be the routing frame.
|
|
request := <-router.RecvChan
|
|
log.Printf("router received '%s' from '%v'", request[1], request[0])
|
|
|
|
// Send a reply. First we send the routing frame, which
|
|
// lets the dealer know which client to send the message.
|
|
router.SendChan <- [][]byte{request[0], []byte("World")}
|
|
log.Printf("router sent 'World'")
|
|
|
|
// Receive the reply.
|
|
reply := <-dealer.RecvChan
|
|
log.Printf("dealer received '%s'", string(reply[0]))
|
|
}
|
|
```
|
|
#### Output
|
|
```
|
|
2015/05/26 21:56:43 router created and bound
|
|
2015/05/26 21:56:43 dealer created and connected
|
|
2015/05/26 21:56:43 dealer sent 'Hello'
|
|
2015/05/26 21:56:43 received 'Hello' from '[0 12 109 153 35]'
|
|
2015/05/26 21:56:43 router sent 'World'
|
|
2015/05/26 21:56:43 dealer received 'World'
|
|
```
|
|
## GoDoc
|
|
[godoc](https://godoc.org/github.com/zeromq/goczmq)
|
|
|
|
## See Also
|
|
* [Peter Kleiweg's](https://github.com/pebbe) [zmq4](https://github.com/pebbe/zmq4) bindings
|
|
|
|
## License
|
|
This project uses the MPL v2 license, see LICENSE
|