D0tNet4Fun / mql-nng

NNG bindings for MQL (MT5)
MIT License
3 stars 1 forks source link

Publisher & Subscriber Socket #5

Closed aalfath closed 1 year ago

aalfath commented 1 year ago

Hi,

I know that this project has not been updated for quite some time.

However, I was wondering if you would update it to include publisher and subscriber socket?

This would be a great addition to the library since the pair0 socket seems to have a limitation because a message can only be sent to 1 receiver.

Thanks a lot!

D0tNet4Fun commented 1 year ago

Yes, it's been a while since I worked on this. I didn't get the chance to use it for myself, or else I would have updated it more often. I am glad you find it useful. Let me see what I can do.

aalfath commented 1 year ago

Thank you very much! Your code is the only publicly available NNG bindings for MQL5 and it's indeed useful. I use it to relay order informations from 1 master account to slave accounts so those information can be used by the slave accounts (either the orders are copied, or to be processed even further by the clients).

For now I use bus socket as a workaround. All clients seem to be able to receive the messages send by the server. But of course this is not quite ideal from topology perspective.

I tried to modify your code to support pub/sub pattern but I am stuck with setting up the nng_setopt() option to allow all topics in the dialers/clients (https://nanomsg.org/gettingstarted/nng/pubsub.html).

Thanks again!

D0tNet4Fun commented 1 year ago

I added 2 new classes PublsiherSocket and SubscriberSocket that have extra behavior when compared to the other sockets.

First use the PublisherSocket to send messages associated with a topic using method SendMessage("topic", message), or just SendMessage(message) to send messages without any topic. When the message has a topic, the message body is automatically updated to include the topic in the beginning of the body.

Then use SubscriberSocket to receive the messages. You must specify what topics are of interest using either SubscribeAll() to receive everything, or Subscribe("topic") to filter out the messages. When no subscriptions are specified the socket seems to discard all messages.

When the message contains a topic it's a bit tricky to get the data, because the topic is part of the message body. This is how pub-sub works in NNG. You have to know what the topic was and then use message.GetData(out, topicLength) to read the data from the body starting at that offset. Example:

pub.SendMessage("topic1", inMsg);
sub.ReceiveMessage(outMsg);
string data;
outMsg.GetData(data, Message::GetTopicLength("topic1"));

A sub socket can subscribe to multiple topics. When the message is received by this socket you can use msg.GetTopic() to get the topic and then pass its length as the offset when calling msg.GetData:

sub.ReceiveMessage(msg);
string topic = msg.GetTopic(); // but only if the message is expected to have a topic, otherwise it's bad!
msg.GetData(data, Message::GetTopicLength(topic));

Take a look at Scripts/PubSubTests.mq5 for more guidance.