// ZmqRecvMulti Receives a multi-part message and return it as a slice of strings func ZmqRecvMulti(s *zmq.Socket) []string { var msg []string more := true for more { part, _ := s.Recv(0) msg = append(msg, part) more, _ = s.GetRcvmore() } return msg }
func RecieveClientRequest(receiver *zmq.Socket, myservices map[string]ProcessRequest) (service_required ProcessRequest, message string, err error) { for count := 0; ; count++ { var request string request, err = receiver.Recv(0) if err != nil { err = errors.New(fmt.Sprintf("Error:Receive:%s", err)) return } fmt.Println("\tCurrent: ", request) // Retrieve message parts from the envelope // The first part is either: // a. A heartbeat request // b. The service's SID // The second part: the message if count == 0 { var isPresent bool service_required, isPresent = myservices[request] fmt.Printf("%s is present? %s", request, isPresent) if !isPresent { err = errors.New("Error:InvalidService") return } } if count == 1 { message = request } // Check if there are more in envelope and deal with any errors var more bool more, err = receiver.GetRcvmore() if err != nil { err = errors.New(fmt.Sprintf("Error:Receive:%s", err)) return } if !more { return } } }
func dump(soc *zmq.Socket) { fmt.Println("----------------------------------------") for { // Process all parts of the message message, _ := soc.Recv(0) // Dump the message as text or binary fmt.Printf("[%03d] ", len(message)) if all_char.MatchString(message) { fmt.Print(message) } else { for i := 0; i < len(message); i++ { fmt.Printf("%02X ", message[i]) } } fmt.Println() more, _ := soc.GetRcvmore() if !more { break } } }
func TestDisconnectInproc(t *testing.T) { var pubSocket, subSocket *zmq.Socket defer func() { for _, s := range []*zmq.Socket{pubSocket, subSocket} { if s != nil { s.SetLinger(0) s.Close() } } }() publicationsReceived := 0 isSubscribed := false pubSocket, err := zmq.NewSocket(zmq.XPUB) if err != nil { t.Fatal("NewSocket XPUB:", err) } subSocket, err = zmq.NewSocket(zmq.SUB) if err != nil { t.Fatal("NewSocket SUB:", err) } err = subSocket.SetSubscribe("foo") if err != nil { t.Fatal("subSocket.SetSubscribe:", err) } err = pubSocket.Bind("inproc://someInProcDescriptor") if err != nil { t.Fatal("pubSocket.Bind:", err) } iteration := 0 poller := zmq.NewPoller() poller.Add(subSocket, zmq.POLLIN) // read publications poller.Add(pubSocket, zmq.POLLIN) // read subscriptions for { sockets, err := poller.Poll(100 * time.Millisecond) if err != nil { t.Error("Poll:", err) break // Interrupted } for _, socket := range sockets { if socket.Socket == pubSocket { for { buffer, err := pubSocket.Recv(0) if err != nil { t.Fatal("pubSocket.Recv", err) } exp := "\x01foo" if isSubscribed { exp = "\x00foo" } if buffer != exp { t.Errorf("pubSocket.Recv: expected %q, got %q", exp, buffer) } if buffer[0] == 0 { if isSubscribed != true { t.Errorf("Poller: expected subscribed") } isSubscribed = false } else { if isSubscribed != false { t.Errorf("Poller: expected not subscribed") } isSubscribed = true } more, err := pubSocket.GetRcvmore() if err != nil { t.Fatal("pubSocket.GetRcvmore:", err) } if !more { break // Last message part } } break } } for _, socket := range sockets { if socket.Socket == subSocket { for _, exp := range []string{"foo", "this is foo!", "", ""} { msg, err := subSocket.Recv(0) if err != nil { t.Fatal("subSocket.Recv:", err) } if msg != exp { t.Errorf("subSocket.Recv: expected %q, got %q", exp, msg) } more, err := subSocket.GetRcvmore() if err != nil { t.Fatal("subSocket.GetRcvmore:", err) } if !more { publicationsReceived++ break // Last message part } } break } } if iteration == 1 { err := subSocket.Connect("inproc://someInProcDescriptor") if err != nil { t.Fatal("subSocket.Connect", err) } } if iteration == 4 { err := subSocket.Disconnect("inproc://someInProcDescriptor") if err != nil { t.Fatal("subSocket.Disconnect", err) } } if iteration > 4 && len(sockets) == 0 { break } _, err = pubSocket.Send("foo", zmq.SNDMORE) if err != nil { t.Fatal("pubSocket.Send 1", err) } _, err = pubSocket.Send("this is foo!", 0) if err != nil { t.Fatal("pubSocket.Send 2", err) } iteration++ } if publicationsReceived != 3 { t.Error("publicationsReceived != 3 ") } if isSubscribed { t.Error("isSubscribed") } err = pubSocket.Close() pubSocket = nil if err != nil { t.Error("pubSocket.Close:", err) } err = subSocket.Close() subSocket = nil if err != nil { t.Error("subSocket.Close:", err) } }
func bounce(server, client *zmq.Socket) (msg string, err error) { content := "12345678ABCDEFGH12345678abcdefgh" // Send message from client to server rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT) if err != nil { return "client.Send SNDMORE|DONTWAIT:", err } if rc != 32 { return "client.Send SNDMORE|DONTWAIT:", err32 } rc, err = client.Send(content, zmq.DONTWAIT) if err != nil { return "client.Send DONTWAIT:", err } if rc != 32 { return "client.Send DONTWAIT:", err32 } // Receive message at server side msg, err = server.Recv(0) if err != nil { return "server.Recv 1:", err } // Check that message is still the same if msg != content { return "server.Recv 1:", errors.New(fmt.Sprintf("%q != %q", msg, content)) } rcvmore, err := server.GetRcvmore() if err != nil { return "server.GetRcvmore 1:", err } if !rcvmore { return "server.GetRcvmore 1:", errors.New(fmt.Sprint("rcvmore ==", rcvmore)) } // Receive message at server side msg, err = server.Recv(0) if err != nil { return "server.Recv 2:", err } // Check that message is still the same if msg != content { return "server.Recv 2:", errors.New(fmt.Sprintf("%q != %q", msg, content)) } rcvmore, err = server.GetRcvmore() if err != nil { return "server.GetRcvmore 2:", err } if rcvmore { return "server.GetRcvmore 2:", errors.New(fmt.Sprint("rcvmore == ", rcvmore)) } // The same, from server back to client // Send message from server to client rc, err = server.Send(content, zmq.SNDMORE) if err != nil { return "server.Send SNDMORE:", err } if rc != 32 { return "server.Send SNDMORE:", err32 } rc, err = server.Send(content, 0) if err != nil { return "server.Send 0:", err } if rc != 32 { return "server.Send 0:", err32 } // Receive message at client side msg, err = client.Recv(0) if err != nil { return "client.Recv 1:", err } // Check that message is still the same if msg != content { return "client.Recv 1:", errors.New(fmt.Sprintf("%q != %q", msg, content)) } rcvmore, err = client.GetRcvmore() if err != nil { return "client.GetRcvmore 1:", err } if !rcvmore { return "client.GetRcvmore 1:", errors.New(fmt.Sprint("rcvmore ==", rcvmore)) } // Receive message at client side msg, err = client.Recv(0) if err != nil { return "client.Recv 2:", err } // Check that message is still the same if msg != content { return "client.Recv 2:", errors.New(fmt.Sprintf("%q != %q", msg, content)) } rcvmore, err = client.GetRcvmore() if err != nil { return "client.GetRcvmore 2:", err } if rcvmore { return "client.GetRcvmore 2:", errors.New(fmt.Sprint("rcvmore == ", rcvmore)) } return "OK", nil }
// Send a request to a service func SendRequest(service Service, request, message string) (reply []string, err error) { // Bind to service if not already done var requester *zmq.Socket fmt.Println("Connecting to '", service.Name, "'' at '", service.Address, "'...") requester, err = zmq.NewSocket(zmq.REQ) if err != nil { log.Println(err) return } requester.Connect(service.Address) poller := zmq.NewPoller() poller.Add(requester, zmq.POLLIN) retries_left := REQUEST_RETRIES request_timeout := REQUEST_TIMEOUT if request == PPP_HEARTBEAT { retries_left = 1 request_timeout = 1500 * time.Millisecond } for retries_left > 0 { // Send message // The service required in first packet of envelope // The message for given service in second packet of envelope // Heartbeat messages only contain one message in envelope if request == PPP_HEARTBEAT { _, err = requester.Send(PPP_HEARTBEAT, 0) } else { _, err = requester.Send(request, zmq.SNDMORE) _, err = requester.Send(message, 0) } for expect_reply := true; expect_reply; { // Poll socket for a reply, with timeout var sockets []zmq.Polled sockets, err = poller.Poll(request_timeout) if err != nil { break // Interrupted } // Wait to receive reply if there are no more messages to send if len(sockets) > 0 { // Receive all replies in the envelope before processing var more bool for count := 0; ; count++ { var rep string rep, err = requester.Recv(0) if err != nil { retries_left-- break } reply = append(reply, rep) // Unpacking three parts from the message envelope // The first part: the expected service reply signature // The second part is either: // a. error state (empty if no error) OR // b. the heartbeat reply of the server // The third part: the actual message if count == 0 && rep != service.Reply { err = errors.New("ServiceListOutdated:Bound to wrong service") retries_left = 0 break } if count == 1 && rep != "" && rep != PPP_READY { err = errors.New(rep) retries_left = 0 break } // Break from loop if there are no more messages or // an error condition occurs more, err = requester.GetRcvmore() if !more || err != nil { retries_left-- break } } // If there was an error retrieving the message, then we // should still expect replies if err != nil { break } // All messages retrieved from packet successfully // Leave the retrieve/retry loops retries_left = 0 expect_reply = false } else { retries_left-- if retries_left == 0 { if err == nil { err = errors.New("Error:TimeOut") } requester.Close() return } else { err = nil reply = nil fmt.Println("No response from server, retrying...") // Old socket is confused; close it and open a new one requester.Close() requester, _ = zmq.NewSocket(zmq.REQ) requester.Connect(service.Address) // Recreate poller for new client poller = zmq.NewPoller() poller.Add(requester, zmq.POLLIN) // Send request again, on the new socket if request == PPP_HEARTBEAT { _, err = requester.Send(PPP_HEARTBEAT, 0) } else { _, err = requester.Send(request, zmq.SNDMORE) _, err = requester.Send(message, 0) } } } } } fmt.Println("\tReceived: ", reply) // Deall with invalid/distorted replies first // Followed by heartbeat replies // Then package reply for return to the function caller if len(reply) < 2 { err = errors.New(fmt.Sprintf("Error:UnexpectedReply:%s", err)) requester.Close() return } if reply[1] == PPP_READY { reply = append(reply, reply[1]) } reply = reply[2:] requester.Close() return }
func (w *worker) socketLoop(s *zmq.Socket, send <-chan Data, recv chan<- Data, state zmq.State) { if recv != nil { defer close(recv) } var ( sendBuf Data sendPending bool recvBuf Data recvPending bool ) for { var ( err error sendActive <-chan Data recvActive chan<- Data ) if !sendPending { sendActive = send } if recvPending { recvActive = recv } select { case <-w.notifier: const fullState = zmq.POLLIN | zmq.POLLOUT if state&fullState != fullState { if state, err = s.GetEvents(); err != nil { handleGeneralError(err) return } } case <-w.closer: return case sendBuf, sendPending = <-sendActive: if !sendPending { send = nil } case recvActive <- recvBuf: recvPending = false recvBuf.Bytes = nil } for { loop := false if sendPending && state&zmq.POLLOUT != 0 { flags := zmq.DONTWAIT if sendBuf.More { flags |= zmq.SNDMORE } if _, err = s.SendBytes(sendBuf.Bytes, flags); err == nil { sendPending = false sendBuf.Bytes = nil loop = true } else if !handleIOError(err) { return } if state, err = s.GetEvents(); err != nil { handleGeneralError(err) return } } if !recvPending && state&zmq.POLLIN != 0 { if data, err := s.RecvBytes(zmq.DONTWAIT); err == nil { if more, err := s.GetRcvmore(); err == nil { recvBuf.Bytes = data recvBuf.More = more recvPending = true loop = true } else { handleGeneralError(err) return } } else if !handleIOError(err) { return } if state, err = s.GetEvents(); err != nil { handleGeneralError(err) return } } if !loop { break } } } }
func bounce(server, client *zmq.Socket, willfail bool) { content := "12345678ABCDEFGH12345678abcdefgh" // Send message from client to server rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT) if checkErr0(err, 1) { return } if rc != 32 { checkErr0(errors.New("rc != 32"), 2) } rc, err = client.Send(content, zmq.DONTWAIT) if checkErr0(err, 3) { return } if rc != 32 { checkErr0(errors.New("rc != 32"), 4) } // Receive message at server side msg, err := server.Recv(0) if checkErr0(e(err, willfail), 5) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 6) } rcvmore, err := server.GetRcvmore() if checkErr0(err, 7) { return } if !rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)), 8) return } // Receive message at server side msg, err = server.Recv(0) if checkErr0(err, 9) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 10) } rcvmore, err = server.GetRcvmore() if checkErr0(err, 11) { return } if rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)), 12) return } // The same, from server back to client // Send message from server to client rc, err = server.Send(content, zmq.SNDMORE) if checkErr0(err, 13) { return } if rc != 32 { checkErr0(errors.New("rc != 32"), 14) } rc, err = server.Send(content, 0) if checkErr0(err, 15) { return } if rc != 32 { checkErr0(errors.New("rc != 32"), 16) } // Receive message at client side msg, err = client.Recv(0) if checkErr0(err, 17) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 18) } rcvmore, err = client.GetRcvmore() if checkErr0(err, 19) { return } if !rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)), 20) return } // Receive message at client side msg, err = client.Recv(0) if checkErr0(err, 21) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 22) } rcvmore, err = client.GetRcvmore() if checkErr0(err, 23) { return } if rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)), 24) return } }
func serveFrontend(frontend *zmq.Socket) (back *zmq.Socket) { var header []string var service Service isPresent := false //fmt.Println("\nReceiving message from client...") for { msg, _ := frontend.Recv(0) //fmt.Printf("\tIn-->%s\n", msg) message := strings.SplitN(msg, ":", 2) if more, _ := frontend.GetRcvmore(); more { // If this part of the message contains no service description // treat is as a header if len(message) != 2 { header = append(header, msg) continue } // If the service request is to register a service, register it if message[0] == "register" { back = registerService(message[1], header, frontend) return } // If the service requested is not in the service list then assume // it will be at end of message and treat message as part of header service, isPresent = services[message[0]] if !isPresent { header = append(header, msg) continue } // If the service requested is available send the early parts of // message at this point for key := range header { //fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, header[key]) service.Backend.Send(header[key], zmq.SNDMORE) } header = header[:0] // Empty header to avoid accidental resend below service.Backend.Send(message[1], zmq.SNDMORE) } else { // If the service request is to register a service, register it if message[0] == "register" { back = registerService(message[1], header, frontend) return } // Has the service already been discovered? -If not, discover it if !isPresent { service, isPresent = services[message[0]] } // If the service is still not discovered at this point, then we // have a problem. Report back to client if !isPresent { sendToClient("InvalidService", header, "Invalid Service SID", 0, frontend) break } // Otherwise everything is good fetch the service and send request // Send the assumed header of the message for key := range header { //fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, header[key]) service.Backend.Send(header[key], zmq.SNDMORE) } // Send the rest of the message //fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, message[1]) service.Backend.Send(message[1], 0) //fmt.Println("\tDone") break } } return }
func bounce(server, client *zmq.Socket) { content := "12345678ABCDEFGH12345678abcdefgh" // Send message from client to server rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT) if checkErr0(err) { return } if rc != 32 { checkErr0(errors.New("rc != 32")) } rc, err = client.Send(content, zmq.DONTWAIT) if checkErr0(err) { return } if rc != 32 { checkErr0(errors.New("rc != 32")) } // Receive message at server side msg, err := server.Recv(0) if checkErr0(err) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content))) } rcvmore, err := server.GetRcvmore() if checkErr0(err) { return } if !rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore))) return } // Receive message at server side msg, err = server.Recv(0) if checkErr0(err) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content))) } rcvmore, err = server.GetRcvmore() if checkErr0(err) { return } if rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore))) return } // The same, from server back to client // Send message from server to client rc, err = server.Send(content, zmq.SNDMORE) if checkErr0(err) { return } if rc != 32 { checkErr0(errors.New("rc != 32")) } rc, err = server.Send(content, 0) if checkErr0(err) { return } if rc != 32 { checkErr0(errors.New("rc != 32")) } // Receive message at client side msg, err = client.Recv(0) if checkErr0(err) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content))) } rcvmore, err = client.GetRcvmore() if checkErr0(err) { return } if !rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore))) return } // Receive message at client side msg, err = client.Recv(0) if checkErr0(err) { return } // Check that message is still the same if msg != content { checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content))) } rcvmore, err = client.GetRcvmore() if checkErr0(err) { return } if rcvmore { checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore))) return } }