PDA

View Full Version : IPC using UDP multicast



MrGentleman
24th August 2016, 17:42
Hello folks,

I have a question about multicasting using QUdpSocket.

I am required to implement an event based IPC mechanism. One process should signal events, arbitrary other processes should be able to receive those.
My idea would be to implement a multicast sender to post events and a multicast receiver to receive those events. The message
to be transmitted itself would be serialized using QDataStream with the following byte stream format:

quint(nr of bytes to send) QString(channel name) QString(message name) QByteArray(payload)

Can there occur a problem if the multicast sender transmits the data stream and a client joins the group somewhere in time after the server has sent the first
bytes and before all bytes have been sent? In other words, does the client need to synchronize somehow on the received data?

thanks in advance,
michael

anda_skoa
24th August 2016, 19:33
This is purely dependent on what your message mean, but if you require messages to be seen then UDP might not be a good choice since there is no guarantee that all packets will arrive or arrive in the order they were sent.

Cheers,
_

MrGentleman
25th August 2016, 05:13
Thanks for your reply!

I thought of using UDP due to the possibility of using multicasts - as the IPC project LCM does [1]

By 'message' I mean simply serialized QObjects, e.g. an error object should be sent and received via a dedicated error channel.

Do you know any other technology for implementing a one-to-many communication instead of UDP multicasting?

Best regards,
michael


[1] https://lcm-proj.github.io/

anda_skoa
25th August 2016, 09:30
On an IP based network you have two options, UDP and TCP.

If you need packets to arrive with certainty or require ordering, then you either implement that on top of UDP yourself or use TCP.

As for multicast, the main difference between an UDP multicast and a TCP server sending the same messages to multiple clients is that the in the latter case the server needs to have connections to each client, while a UDP multicaster doesn't need to know if or how many are listening.

Cheers,
_

MrGentleman
25th August 2016, 13:55
Ok, I see, thank you very much.

Can we summarize the following:

Assuming I want to send a serialized QObject (just a series of bytes) using QUdpSocket, this byte stream could be split by the UDP transport layer into single UDP datagrams (e.g. because there are too many bytes in the payload). The receiver then has no guarantee that it can de-serialize (using QDataStream) the received data into the same QObject which has been sent, because the datagrams might be received re-ordered?

Best regards,
michael

anda_skoa
25th August 2016, 14:44
No, I don't think so.

If I remember correctly a UDP datagram either arrives full or not, even when it has been fragmented by a lower layer.

But of course if the application has to split something into multiple UDP datagrams, then any of them might not arrive or out of order.

Cheers,
_

MrGentleman
26th August 2016, 05:44
Ok, so if I simply write my object as 'one' datagram, the subscriber will be able to deserialize the bytes received.



class Publisher : public QUdpSocket {

void publishEvent(MyEvent const& e) {
QByteArray eventData;
QDataStream out(&eventData, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_8);

// Add request-dependent data
out<< e;

writeDatagram(eventData.size(), eventData);
}
}

class Subscriber : public QUdpSocket {

void onReadyRead() {
QByteArray eventData;

do {
eventData.resize(pendingDatagramSize());
readDatagram(eventData.data(), eventData.size());

QDataStream in(&eventData, QIODevice::ReadOnly);

// Get and handle received event data
MyEventData e;
in>> e;

} while (hasPendingDatagrams());
}


The doc for QUdpSocket::writeDatagram() (http://doc.qt.io/qt-4.8/qudpsocket.html#writeDatagram) states that the number of bytes to be sent should not be larger than 512 bytes because in IP layer the data could be fragmented. But isn't the IP layer on the receiver side responsible for reassembilng the data and providing the data for the UDP layer as one datagram? IMHO if due to fragmentation a single IP packet is getting lost, the UDP datagram can not be reassembled and therefore the whole datagram will be lost.

best regards,
michael

anda_skoa
26th August 2016, 12:07
The maximum packet size of IP is 65535 (16bit length field).

Ethernet often has 1500 byte MTU (maximum transfer unit), other technologies have smaller or larger sizes.

Since an IP packet can cross a lot of channels with different size requirements, a single IP packet might be split and reassembled quite a lot along its route.

If, for whatever reason, part of a UDP packet is lost, it can no longer be reassembled by the receiving IP stack and will be discarded.

Since UDP has not retransmit or assumption that packets will arrive this is generally OK, the transmission partners have to deal with packet loss anyway.

The larger a packet is, the higher the chance that it gets fragmented and the more fragments, the higher the chance that one is lost.

The latter chance of course depends a lot on the transmission path.
E.g. in a local ethernet this is not likely to happen at all.

Cheers,
_

MrGentleman
29th August 2016, 06:20
Thank you very much for your input!
Since the IPC mechanism is used only locally on the host machine and the number of bytes to send/receive are less than 200 I will implement
a publisher/subscriber system based on UDP multicast.

Best regards,
michael

anda_skoa
29th August 2016, 09:50
On the loopback device there shouldn't be any problem with packet loss (aside from receiver buffers running full), reordering or packet fragmentation :)

Cheers,
_