为什么客户端水湿从NetMQ框架服务器接收邮件?

问题描述 投票:0回答:1

最近,我用的是NetMQ发送或服务器和客户机之间的接收消息。服务器代码,如:

    void Main()
    {
      CreatePullAndPushSocket();
      Task.Factory.StartNew(()=> {
            while (true)
            {
                Thread.Sleep(1);
                if (Pull != null)
                {
                    var message = Pull.ReceiveFrameString();
                }
            }
        });
    }
    PullSocket Pull;
    PushSocket Push;
    private void CreatePullAndPushSocket()
    {
        Pull = new PullSocket("tcp://ip1:port1");
        Push = new PushSocket("tcp://ip2:port2");
    }
    public void SendMessageToClient(string message)
    {
        if (Push != null)
        {
            Push.SendFrame(message);
        }
    }

客户端代码,如:

   void Main()
    { 
      new Thread(()=> {
            while (true)
            {
                Thread.Sleep(1);
                if (Pull != null)
                {
                    var message = Pull.ReceiveFrameString();
                }
            }
        }).Start();
    }
    PullSocket Pull;
    PushSocket Push;
    private void CreatePullAndPushSocket()
    {
        Pull = new PullSocket("tcp://ip2:port2");
        Push = new PushSocket("tcp://ip1:port1");
    }
    public void SendMessageToClient(string message)
    {
        if (Push != null)
        {
            Push.SendFrame(message);
        }
    }

当我运行两个应用程序,这是服务器应用程序,另一个是客户端应用程序。

  • 1:客户端发送消息到服务器
  • 2:服务器可以从客户端接收消息
  • 3:服务器发送另一个消息客户端
  • 4:客户端水湿收到消息!!!

太奇怪了,我也跟着指导https://netmq.readthedocs.io/en/latest/push-pull/

c# message-queue zeromq netmq
1个回答
0
投票

在NetMQ很重要的一点就是线程模型。真正重要的是,在多线程,则不应使用套接字。所以,如果线程#1创建的套接字比它应该使用它。如果您想从其他线程发送消息(可以说线程#2)使用相同的插座就忘了这件事。您应该以某种方式从线程#2发送messgae主题#1,那么就应该槽插口发送到客户端。

所以basicly CreatePullAndPushSocket是错误的,奇怪的事情能够比happend。你是在一个线程创建套接字和使用等。它完全错误的。

另一件事是你的Thread.Sleep。你不应该使用的Thread.Sleep,因为你的线程休眠1秒,然后一次检查插座,比睡眠和检查一次。 NetMQ具有功能TryReceive,有超时。因此,它可以检查插座1秒钟,退出来检查,如果你打电话取消/停止或别的什么东西。甚至更好的是有轮询,这将套接字听所有的时间,让我们从其他线程调用停止。

让我们看看下面的代码:

private Poller _poller;

public void Start()
{
  Task.Factory.StartNew(()=> {
     using(var pullSocket = new PullSocket("tcp://ip1:port1"))
     using(_poller = new Poller())
     {
        pullSocket.ReceiveReady += (object sender, NetMQSocketEventArgsnetMqSocketEventArgs) =>
        {
            var message = netMqSocketEventArgs.Socket.ReceiveMultipartMessage();
        }
        _poller.Add(pullSocket);
        _poller.Run();
     }
    });
}
public void Stop()
{
   _poller?.Stop();
}

或者,如果你想使用的代码,而与while循环轮询:

私人只读CancellationTokenSource _cts;

public void Start()
{
   _cts = new CancellationTokenSource();
   var token = _cts.Token;

  Task.Factory.StartNew(()=> {
     using(var pullSocket = new PullSocket("tcp://ip1:port1"))
     {
        while (cancellationToken.IsCancellationRequested == false)
        {
            NetMQMessage message = new NetMQMessage();
            bool success = workerSocket.TryReceiveMultipartMessage(TimeSpan.FromSeconds(5), ref message);

            if (success == false)
            {
                continue;
            }

            //if You reach this line, than You have a message
        }
     }
    },
    token,
    TaskCreationOptions.LongRunning,
    TaskScheduler.Default);
}
public void Stop()
{
    _cts.Cancel();
    _cts.Token.WaitHandle.WaitOne();//if You want wait until service will stop
}

所以回到你的问题,你应该在您创建它使用套接字只能从它的线程内。好东西是要在using语句总是释放它最后总是用插座。

我不能看到SendMessageToClient方法的用法,但我认为你是从一些按钮或东西调用它。你可以做,如果一个插座的构造函数从该线程调用。如果你能告诉我你在哪里调用这个方法我可以谈谈这个。

© www.soinside.com 2019 - 2024. All rights reserved.