mhowlett / NNanomsg

.NET binding for nanomsg
MIT License
179 stars 52 forks source link

Polling Issue: ReceivedMessage invoked, but ReceiveStreamImmediate returns null #12

Closed metadings closed 10 years ago

metadings commented 10 years ago

Hello World,

I have a REPly setup like this (broken down):

      var nanoSocket = new NanomsgSocket(Domain.SP, Protocol.REP);
      //nanoSocket.Options.TcpNoDelay = true;
      nanoSocket.Bind("tcp://127.0.0.1:4444");

      var nanoListener = new NanomsgListener();
      nanoListener.AddSocket(nanoSocket);

      while (!cancellor.IsCancellationRequested)
      {
        nanoListener.ReceivedMessage += (socketId) =>
        {

          var reqMemory = new MemoryStream();

          // This often blocks forever:
          // NanomsgReadStream inStream = nanoSocket.ReceiveStream();
          // And this often returns null, despite we "ReceivedMessage": Why?
          NanomsgReadStream inStream = nanoSocket.ReceiveStreamImmediate();
          if (inStream == null) return;

          using (inStream)
          {
            inStream.CopyTo(reqMemory);
            inStream.Close();
          }

          reqMemory.Seek(0, SeekOrigin.Begin);
          var reqMessage = Unpacker.Create(reqMemory);

          // ...

          { // send REP
            var repMemory = new MemoryStream();
            var repMessage = Packer.Create(repMemory);
            // ...

            repMemory.Seek(0, SeekOrigin.Begin);
            using (NanomsgWriteStream outStream = nanoSocket.CreateSendStream())
            {
              repMemory.WriteTo(outStream);
              nanoSocket.SendStream(outStream);
              outStream.Flush();
              outStream.Close();
            }

          }

        };
        nanoListener.Listen(TimeSpan.FromMilliseconds(1000));

      } // loop

      nanoSocket.Dispose();

The core of this is, that the while is cancelable with a CancellationTokenSource, and the nanoListener polls every while for a second.

Now the problem (besides missing some named fields in NanomsgSymbols when using Send/ReceiveStreamImmediate) is, that the ReceivedMessage delegate is often called but ReceiveStreamImmediate returns null (and the non-Immediate methods block forever).

Why is the delegate called, when there is no message anymore?

metadings commented 10 years ago

Hell I got it, I recreated the ReceivedMessage delegate every while.

Someone maintaining this project, please add the following named fields to the NanomsgSymbol class:

namespace NNanomsg
{
    public static class NanomsgSymbols
    {
//...

        public static readonly int

            NN_NS_NAMESPACE,
            NN_NS_VERSION,
            NN_NS_DOMAIN,
            NN_NS_TRANSPORT,
            NN_NS_PROTOCOL,
            NN_NS_OPTION_LEVEL,
            NN_NS_SOCKET_OPTION,
            NN_NS_TRANSPORT_OPTION,
            NN_NS_OPTION_TYPE,
            NN_NS_FLAG,
            NN_NS_ERROR,
            NN_NS_LIMIT,
            NN_TYPE_NONE,
            NN_TYPE_INT,
            NN_TYPE_STR,
            NN_UNIT_NONE,
            NN_UNIT_BYTES,
            NN_UNIT_MILLISECONDS,
            NN_UNIT_PRIORITY,
            NN_UNIT_BOOLEAN,
            NN_SOCKET_NAME,
// ...