NetMQ:NetMQPoller可以处理异步消息发送吗?

时间:2020-07-15 20:01:28

标签: c# async-await zeromq netmq

有人可以结合使用NetMQPoller和异步任务发送消息的示例吗?

// 1. Receive a message from one of many clients
// 2. Handle client requests on multiple async Task's (may be file bound)
// 3. Respond to clients when long running Task finishes

我们当前正在使用非常准系统的“经销商/路由器”设置,以便多个客户端与单个服务器通信。在服务器上,我们将每个客户端请求传递到处理请求的任务/线程池,生成响应,然后尝试响应原始客户端。因为我是新来的,所以我没有意识到在不同的Task / Thread上调用客户端会使事情变糟,但是现在这很有意义。

我正在寻找的是正确的处理方式。我肯定可以有一个BlockingCollection消息来发送回去,并仅从原始线程中对其进行服务,但是最近我发现了 NetMQPoller ,听起来好像它内置了其中一些。我不是100%确定它是否可以帮助我在原始线程上发送消息,但是它的很多部分听起来很有希望。谁能指出我的示例,该示例是从路由器/服务器在与接收原始消息不同的线程上将消息发送回路由器/服务器的。

更新 我想我可以通过合并来解决我自己的问题

    class Program
    {
        static void Main( string[] args )
        {
            // NOTES
            // 1. Use ThreadLocal<DealerSocket> where each thread has
            //    its own client DealerSocket to talk to server
            // 2. Each thread can send using it own socket
            // 3. Each thread socket is added to poller
            const int delay = 3000; // millis
            var clientSocketPerThread = new ThreadLocal<DealerSocket>();

            using( var server = new RouterSocket("@tcp://127.0.0.1:5556") )
            using( var queue = new NetMQQueue<MyResponse>() )
            using( var poller = new NetMQPoller { queue } )
            {
                // Start some threads, each with its own DealerSocket
                // to talk to the server socket. Creates lots of sockets,
                // but no nasty race conditions no shared state, each
                // thread has its own socket, happy days.
                for( int i = 0; i < 3; i++ )
                {
                    Task.Factory.StartNew(state =>
                    {
                        DealerSocket client = null;
                        if( !clientSocketPerThread.IsValueCreated )
                        {
                            client = new DealerSocket();
                            client.Options.Identity =
                                Encoding.Unicode.GetBytes(state.ToString());
                            client.Connect("tcp://127.0.0.1:5556");
                            client.ReceiveReady += Client_ReceiveReady;
                            clientSocketPerThread.Value = client;
                            poller.Add(client);
                        }
                        else
                        {
                            client = clientSocketPerThread.Value;
                        }

                        while( true )
                        {
                            var messageToServer = new NetMQMessage();
                            messageToServer.AppendEmptyFrame();
                            messageToServer.Append(state.ToString());
                            Console.WriteLine("======================================");
                            Console.WriteLine(" OUTGOING MESSAGE TO SERVER ");
                            Console.WriteLine("======================================");
                            PrintFrames("Client Sending", messageToServer);
                            client.SendMultipartMessage(messageToServer);
                            Thread.Sleep(delay);
                        }
                    }, string.Format("client {0}", i), TaskCreationOptions.LongRunning);
                }

                queue.ReceiveReady += ( sender, e ) =>
                {
                    var queueItem = e.Queue.Dequeue();

                    var messageToClient = new NetMQMessage();
                    messageToClient.Append(queueItem.ClientId);
                    messageToClient.AppendEmptyFrame();
                    messageToClient.Append(queueItem.MessageToClient);
                    server.SendMultipartMessage(messageToClient);
                };

                // start the poller
                poller.RunAsync();

                // server loop
                while( true )
                {
                    var clientMessage = server.ReceiveMultipartMessage();
                    Console.WriteLine("======================================");
                    Console.WriteLine(" INCOMING CLIENT MESSAGE FROM CLIENT ");
                    Console.WriteLine("======================================");
                    PrintFrames("Server receiving", clientMessage);
                    if( clientMessage.FrameCount == 3 )
                    {
                        var clientAddress = clientMessage[0];
                        var clientOriginalMessage = clientMessage[2].ConvertToString();
                        string response = string.Format("{0} back from server {1}",
                            clientOriginalMessage, DateTime.Now.ToLongTimeString());

                        Task.Factory.StartNew(async() =>
                        {
                            await Task.Delay(200);

                            var clientResponse = new MyResponse()
                            {
                                ClientId = clientAddress,
                                MessageToClient = response
                            };
                            queue.Enqueue(clientResponse);
                        }, TaskCreationOptions.LongRunning);
                    }
                }
            }
        }

        static void PrintFrames( string operationType, NetMQMessage message )
        {
            for( int i = 0; i < message.FrameCount; i++ )
            {
                Console.WriteLine("{0} Socket : Frame[{1}] = {2}", operationType, i,
                    message[i].ConvertToString());
            }
        }

        static void Client_ReceiveReady( object sender, NetMQSocketEventArgs e )
        {
            bool hasmore = false;
            e.Socket.ReceiveFrameString(out hasmore);
            if( hasmore )
            {
                string result = e.Socket.ReceiveFrameString(out hasmore);
                Console.WriteLine("REPLY {0}", result);
            }
        }

        class MyResponse
        {
            public NetMQFrame ClientId;

            public string MessageToClient;
        }
    }

0 个答案:

没有答案