static int Main(string[] args) { if (args.Length != 3) { Console.WriteLine("usage: remote_lat remote_lat <connect-to> <message-size> <roundtrip-count>"); return 1; } string connectTo = args[0]; int messageSize = int.Parse(args[1]); int roundtripCount = int.Parse(args[2]); var context = ZMQ.CtxNew(); var reqSocket = ZMQ.Socket(context, ZmqSocketType.Req); bool connected = reqSocket.Connect(connectTo); if (!connected) { Console.WriteLine("error in zmq_connect"); } var message = new Msg(messageSize); var stopWatch = Stopwatch.StartNew(); for (int i = 0; i != roundtripCount; i++) { bool sent = reqSocket.Send(message, SendRecieveOptions.None); if (!sent) { Console.WriteLine("error in zmq_sendmsg"); return -1; } message = reqSocket.Recv(SendRecieveOptions.None); if (message.Size != messageSize) { Console.WriteLine("message of incorrect size received. Received: " + message.Size + " Expected: " + messageSize); return -1; } } stopWatch.Stop(); message.Close(); double elapsedMicroseconds = stopWatch.ElapsedTicks * 1000000 / Stopwatch.Frequency; double latency = elapsedMicroseconds / (roundtripCount * 2); Console.WriteLine("message size: {0} [B]", messageSize); Console.WriteLine("roundtrip count: {0}", roundtripCount); Console.WriteLine("average latency: {0:0.000} [µs]", latency); reqSocket.Close(); context.Terminate(); return 0; }
public void Plug(IOThread ioThread, SessionBase session) { m_encoder.SetMsgSource(session); AddFd(m_socket); SetPollout(m_socket); // get the first message from the session because we don't want to send identities Msg msg = new Msg(); msg.InitEmpty(); bool ok = session.PullMsg(ref msg); if (ok) { msg.Close(); } }
// Remove any half processed messages. Flush unflushed messages. // Call this function when engine disconnect to get rid of leftovers. private void CleanPipes() { if (m_pipe != null) { // Get rid of half-processed messages in the out pipe. Flush any // unflushed messages upstream. m_pipe.Rollback(); m_pipe.Flush(); // Remove any half-read message from the in pipe. while (m_incompleteIn) { Msg msg = PullMsg(); if (msg == null) { Debug.Assert(!m_incompleteIn); break; } msg.Close(); } } }
static XSub() { s_sendSubscription = (data, size, arg) => { Pipe pipe = (Pipe) arg; // Create the subsctription message. Msg msg = new Msg(size + 1); msg.Put((byte)1); msg.Put(data,1, size); // Send it to the pipe. bool sent = pipe.Write (msg); // If we reached the SNDHWM, and thus cannot send the subscription, drop // the subscription message instead. This matches the behaviour of // zmq_setsockopt(ZMQ_SUBSCRIBE, ...), which also drops subscriptions // when the SNDHWM is reached. if (!sent) msg.Close (); }; }
static XSub() { s_sendSubscription = (data, size, arg) => { Pipe pipe = (Pipe)arg; // Create the subsctription message. Msg msg = new Msg(size + 1); msg.Put((byte)1); msg.Put(data, 1, size); // Send it to the pipe. bool sent = pipe.Write(msg); // If we reached the SNDHWM, and thus cannot send the subscription, drop // the subscription message instead. This matches the behaviour of // zmq_setsockopt(ZMQ_SUBSCRIBE, ...), which also drops subscriptions // when the SNDHWM is reached. if (!sent) { msg.Close(); } }; }
protected override void ProcessPipeTermAck() { // Notify the user that all the references to the pipe should be dropped. Debug.Assert(m_sink != null); m_sink.Terminated(this); // In terminating and double_terminated states there's nothing to do. // Simply deallocate the pipe. In terminated state we have to ack the // peer before deallocating this side of the pipe. All the other states // are invalid. if (m_state == State.Terminated) { m_outboundPipe = null; SendPipeTermAck(m_peer); } else { Debug.Assert(m_state == State.Terminating || m_state == State.DoubleTerminated); } // We'll deallocate the inbound pipe, the peer will deallocate the outbound // pipe (which is an inbound pipe from its point of view). // First, delete all the unread messages in the pipe. We have to do it by // hand because msg_t doesn't have automatic destructor. Then deallocate // the ypipe itself. var msg = new Msg(); if (m_inboundPipe != null) { while (m_inboundPipe.Read(ref msg)) { msg.Close(); } } m_inboundPipe = null; }
protected override void XReadActivated(Pipe pipe) { // There are some subscriptions waiting. Let's process them. Msg sub = new Msg(); while (pipe.Read(ref sub)) { // Apply the subscription to the trie. byte[] data = sub.Data; int size = sub.Size; if (size > 0 && (data[0] == 0 || data[0] == 1)) { bool unique; if (data[0] == 0) { unique = m_subscriptions.Remove(data, 1, size - 1, pipe); } else { unique = m_subscriptions.Add(data, 1, size - 1, pipe); } // If the subscription is not a duplicate, store it so that it can be // passed to used on next recv call. if (m_options.SocketType == ZmqSocketType.Xpub && (unique || m_verbose)) { m_pending.Enqueue(new Blob(sub.Data, sub.Size)); } } else // process message unrelated to sub/unsub { m_pending.Enqueue(new Blob(sub.Data, sub.Size)); } sub.Close(); } }
protected override void ProcessHiccup(object pipe) { // Destroy old out-pipe. Note that the read end of the pipe was already // migrated to this thread. Debug.Assert(m_outboundPipe != null); m_outboundPipe.Flush(); var msg = new Msg(); while (m_outboundPipe.Read(ref msg)) { msg.Close(); } // Plug in the new out-pipe. Debug.Assert(pipe != null); m_outboundPipe = (YPipe <Msg>)pipe; m_outActive = true; // If appropriate, notify the user about the hiccup. if (m_state == State.Active) { m_sink.Hiccuped(this); } }
public virtual void PushMsg(ref Msg msg) { // First message to receive is identity (if required). if (!m_identityReceived) { msg.SetFlags(MsgFlags.Identity); m_identityReceived = true; if (!m_options.RecvIdentity) { msg.Close(); msg.InitEmpty(); return; } } if (m_pipe != null && m_pipe.Write(ref msg)) { msg.InitEmpty(); return; } throw AgainException.Create(); }
public virtual bool PushMsg(ref Msg msg) { // First message to receive is identity (if required). if (!m_identityReceived) { msg.SetFlags(MsgFlags.Identity); m_identityReceived = true; if (!m_options.RecvIdentity) { msg.Close(); msg.InitEmpty(); return(true); } } if (m_pipe != null && m_pipe.Write(ref msg)) { msg.InitEmpty(); return(true); } return(false); }
protected override void ProcessHiccup(object pipe) { // Destroy old out-pipe. Note that the read end of the pipe was already // migrated to this thread. Debug.Assert(m_outboundPipe != null); m_outboundPipe.Flush(); var msg = new Msg(); while (m_outboundPipe.Read(out msg)) { msg.Close(); } // Plug in the new out-pipe. Debug.Assert(pipe != null); m_outboundPipe = (YPipe<Msg>)pipe; m_outActive = true; // If appropriate, notify the user about the hiccup. if (m_state == State.Active) m_sink.Hiccuped(this); }
protected override bool XSend(ref Msg msg, SendReceiveOptions flags) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (!m_moreOut) { Debug.Assert(m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. // TODO: The connections should be killed instead. if (msg.HasMore) { m_moreOut = true; // Find the pipe associated with the identity stored in the prefix. // If there's no such pipe just silently ignore the message, unless // mandatory is set. Blob identity = new Blob(msg.Data, msg.Size); Outpipe op; if (m_outpipes.TryGetValue(identity, out op)) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite()) { op.Active = false; m_currentOut = null; if (m_mandatory) { m_moreOut = false; return(false); } } } else if (m_mandatory) { m_moreOut = false; throw NetMQException.Create(ErrorCode.EHOSTUNREACH); } } // Detach the message from the data buffer. msg.Close(); msg.InitEmpty(); return(true); } if (m_options.RawSocket) { msg.ResetFlags(MsgFlags.More); } // Check whether this is the last part of the message. m_moreOut = msg.HasMore; // Push the message into the pipe. If there's no out pipe, just drop it. if (m_currentOut != null) { // Close the remote connection if user has asked to do so // by sending zero length message. // Pending messages in the pipe will be dropped (on receiving term- ack) if (m_rawSocket && msg.Size == 0) { m_currentOut.Terminate(false); msg.Close(); msg.InitEmpty(); m_currentOut = null; return(true); } bool ok = m_currentOut.Write(ref msg); if (!ok) { m_currentOut = null; } else if (!m_moreOut) { m_currentOut.Flush(); m_currentOut = null; } } else { msg.Close(); } // Detach the message from the data buffer. msg.InitEmpty(); return(true); }
public bool Send(Msg msg, SendRecieveOptions flags) { // Drop the message if required. If we are at the end of the message // switch back to non-dropping mode. if (m_dropping) { m_more = msg.HasMore; m_dropping = m_more; msg.Close (); return true; } while (m_active > 0) { if (m_pipes[m_current].Write (msg)) break; Debug.Assert(!m_more); m_active--; if (m_current < m_active) Utils.Swap (m_pipes, m_current, m_active); else m_current = 0; } // If there are no pipes we cannot send the message. if (m_active == 0) { ZError.ErrorNumber = ErrorNumber.EAGAIN; return false; } // If it's part of the message we can fluch it downstream and // continue round-robinning (load balance). m_more = msg.HasMore; if (!m_more) { m_pipes[m_current].Flush(); if (m_active > 1) m_current = (m_current + 1) % m_active; } return true; }
// Remove any half processed messages. Flush unflushed messages. // Call this function when engine disconnect to get rid of leftovers. private void CleanPipes() { if (m_pipe != null) { // Get rid of half-processed messages in the out pipe. Flush any // unflushed messages upstream. m_pipe.Rollback(); m_pipe.Flush(); // Remove any half-read message from the in pipe. while (m_incompleteIn) { var msg = new Msg(); msg.InitEmpty(); if (!PullMsg(ref msg)) { Debug.Assert(!m_incompleteIn); break; } msg.Close(); } } }
private bool IdentifyPeer(Pipe pipe) { Blob identity; if (m_options.RawSocket) { // Always assign identity for raw-socket byte[] buf = new byte[5]; buf[0] = 0; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, buf, 1, 4); identity = new Blob(buf, buf.Length); } else { // Pick up handshake cases and also case where next identity is set Msg msg = new Msg(); msg.InitEmpty(); bool ok = pipe.Read(ref msg); if (!ok) { return(false); } if (msg.Size == 0) { // Fall back on the auto-generation byte[] buf = new byte[5]; buf[0] = 0; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, buf, 1, 4); identity = new Blob(buf, buf.Length); msg.Close(); } else { identity = new Blob(msg.Data, msg.Size); // Ignore peers with duplicate ID. if (m_outpipes.ContainsKey(identity)) { msg.Close(); return(false); } msg.Close(); } } pipe.Identity = identity; // Add the record into output pipes lookup table Outpipe outpipe = new Outpipe(pipe, true); m_outpipes.Add(identity, outpipe); return(true); }
/// <summary> /// Remove unfinished parts of the outbound message from the pipe. /// </summary> public void Rollback() { // Remove incomplete message from the outbound pipe. if (m_outboundPipe != null) { var msg = new Msg(); while (m_outboundPipe.Unwrite(ref msg)) { Debug.Assert(msg.HasMore); msg.Close(); } } }
public override void Destroy() { base.Destroy(); m_prefetchedMsg.Close(); }
public override void Destroy() { base.Destroy(); m_message.Close(); }
protected override void ProcessPipeTermAck() { // Notify the user that all the references to the pipe should be dropped. Debug.Assert(m_sink != null); m_sink.Terminated(this); // In terminating and double_terminated states there's nothing to do. // Simply deallocate the pipe. In terminated state we have to ack the // peer before deallocating this side of the pipe. All the other states // are invalid. if (m_state == State.Terminated) { m_outboundPipe = null; SendPipeTermAck(m_peer); } else Debug.Assert(m_state == State.Terminating || m_state == State.DoubleTerminated); // We'll deallocate the inbound pipe, the peer will deallocate the outbound // pipe (which is an inbound pipe from its point of view). // First, delete all the unread messages in the pipe. We have to do it by // hand because msg_t doesn't have automatic destructor. Then deallocate // the ypipe itself. var msg = new Msg(); while (m_inboundPipe.Read(out msg)) { msg.Close(); } m_inboundPipe = null; }
public virtual bool PushMsg(ref Msg msg) { // First message to receive is identity (if required). if (!m_identityReceived) { msg.SetFlags(MsgFlags.Identity); m_identityReceived = true; if (!m_options.RecvIdentity) { msg.Close(); msg.InitEmpty(); return true; } } if (m_pipe != null && m_pipe.Write(ref msg)) { msg.InitEmpty(); return true; } return false; }