func TestSocketEvent(t *testing.T) { var rep *zmq.Socket defer func() { if rep != nil { rep.SetLinger(0) rep.Close() } }() // REP socket rep, err := zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } // REP socket monitor, all events err = rep.Monitor("inproc://monitor.rep", zmq.EVENT_ALL) if err != nil { t.Fatal("rep.Monitor:", err) } chMsg := make(chan string, 10) go rep_socket_monitor("inproc://monitor.rep", chMsg) time.Sleep(time.Second) // Generate an event err = rep.Bind("tcp://*:9689") if err != nil { t.Fatal("rep.Bind:", err) } rep.Close() rep = nil expect := []string{ "EVENT_LISTENING tcp://0.0.0.0:9689", "EVENT_CLOSED tcp://0.0.0.0:9689", "Done", } i := 0 for msg := range chMsg { if i < len(expect) { if msg != expect[i] { t.Errorf("Expected message %q, got %q", expect[i], msg) } i++ } else { t.Error("Unexpected message: %q", msg) } } for ; i < len(expect); i++ { t.Errorf("Expected message %q, got nothing", expect[i]) } }
// // MonitorSocket creates a monitoring socket using given context and connects // to a given socket to be monitored. Returns a channel to receive monitoring // events. See event definitions here: http://api.zeromq.org/3-2:zmq-socket-monitor // func MonitorSocket(socket *zmq.Socket, name string) (<-chan zmq.Event, error) { endpoint := fmt.Sprintf("inproc://%v.%v.%v", name, os.Getpid(), time.Now().UnixNano()) monCh := make(chan zmq.Event, 512) // make a buffered channel in case of heavy network activity go func() { monSock, err := zmq.NewSocket(zmq.PAIR) if err != nil { log.Println("Failed to start monitoring socket:", err.Error()) return } monSock.Connect(endpoint) for { data, err := monSock.RecvMessageBytes(0) if err != nil { return } eventID := zmq.Event(binary.LittleEndian.Uint16(data[0][:2])) /* switch eventID { case zmq.EVENT_CONNECTED: log.Println("MonitorSocket: EVENT_CONNECTED", string(data[1])) case zmq.EVENT_CONNECT_DELAYED: log.Println("MonitorSocket: EVENT_CONNECT_DELAYED", string(data[1])) case zmq.EVENT_CONNECT_RETRIED: log.Println("MonitorSocket: EVENT_CONNECT_RETRIED", string(data[1])) case zmq.EVENT_LISTENING: log.Println("MonitorSocket: EVENT_LISTENING", string(data[1])) case zmq.EVENT_BIND_FAILED: log.Println("MonitorSocket: EVENT_BIND_FAILED", string(data[1])) case zmq.EVENT_ACCEPTED: log.Println("MonitorSocket: EVENT_ACCEPTED", string(data[1])) case zmq.EVENT_ACCEPT_FAILED: log.Println("MonitorSocket: EVENT_ACCEPT_FAILED", string(data[1])) case zmq.EVENT_CLOSED: log.Println("MonitorSocket: EVENT_CLOSED", string(data[1])) case zmq.EVENT_CLOSE_FAILED: log.Println("MonitorSocket: EVENT_CLOSE_FAILED", string(data[1])) case zmq.EVENT_DISCONNECTED: log.Println("MonitorSocket: EVENT_DISCONNECTED", string(data[1])) default: log.Printf("MonitorSocket: Unsupported event id: %#v - Message: %#v", eventID, data) } */ monCh <- zmq.Event(eventID) } }() return monCh, socket.Monitor(endpoint, MonitorEvents) }
// NewClientWithConnection returns a new Client to handle requests to the // set of services at the other end of the connection. // An existing connection in the form of a zmq socket together with the zmq // context they were created with is used func NewClientWithConnection(ctx *zmq.Context, conn *zmq.Socket) *Client { // A router socket is the middle-man between client requests and actually sending/receiving on the wire router, err := ctx.NewSocket(zmq.ROUTER) if err != nil { glog.Fatal(err) } if err := router.Bind(RouterURL); err != nil { glog.Fatal(err) } client := &Client{ conn: conn, endpoints: endpoints{ socket: conn, }, router: router, ctx: ctx, } // Start the proxy in an own routine since it is blocking go func() { if err := zmq.Proxy(conn, router, nil); err != nil { switch zmq.AsErrno(err) { case zmq.Errno(zmq.ETERM): glog.Info(err) case zmq.Errno(syscall.EINTR): glog.Info(err) default: glog.Info(zmq.AsErrno(err)) glog.Info(err) } client.Close() } }() // Socket monitor for connect event monitorURL := "inproc://monitor" if err := conn.Monitor(monitorURL, zmq.EVENT_CONNECTED|zmq.EVENT_DISCONNECTED); err != nil { client.Close() glog.Fatal(err) } go client.monitor(monitorURL) return client }