UDP vs TCP (I write this intro to prepare the ground for my description as to why UDP is wrong on the Spark Core.)
TCP is a “connected” protocol. The read and writes happen to a “stream” of bytes which are guaranteed to arrive in order (or not at all - subsequent bytes only arrive if the intermediate bytes arrive - there are no gaps and no re-ordering). The data is not packetised from the application’s POV. (The number of reads and writes may differ, and the write boundaries are not respected. You send 100 bytes and then 300 and then 200, and the other side reads this how they choose, possibly in equal lumps 150, 150, 150, 150.)
UDP is a “connectionless” protocol. The reads and writes happen to individual “datagrams”. The order of arrival is not guaranteed, arrival is not guaranteed. One write creates one datagram. One read reads one datagram. Even if that read is partial, the next read reads another datagram, and not the next one sent, necessarily. The number of reads will be the same as the number of writes [or less if a datagram is lost or more if a datagram is duplicated]. A datagram arrives in its entirety or not at all. (E.g. The sender sends datagrams A, then B, then C each of 100 bytes. The reader chooses to do three reads each limited to 20 bytes. The first read just happens to read datagram C, and because only 20 bytes are read the remaining bytes of that datagram are lost, the second read happens to return the first 20 bytes of datagram A, and datagram B never arrives. The subsequent 80 bytes of A & C are lost too, but by choice - the whole datagram arrives or not at all.)
Why anyone might want to use UDP rather than TCP
On Spark Core I decided to use UDP for the usual reasons. I do not mind if I miss the odd message (i.e. datagram), I do not care if the order of the messages is mangled a little. But I do not want to write the code to work out the boundaries between the messages or to reassemble messages across different reads.
Code demonstrating the issue
In plain old C on a *ix box I created a UDP datagram socket and wrote to it thusly, all the irrelevant code removed:
strcpy( buf, "123");
sockfd=socket(AF_INET,SOCK_DGRAM,0);
for( i=0; i<10; i++) {
sendto( sockfd, buf, strlen(buf), 0,
(struct sockaddr *)&servaddr, sizeof(servaddr));
}
On the Spark Core I read the packets like this:
sbuf[0] = '\0';
udp.begin(32000);
for( ; ; ) {
if( 0 < (packetSize = udp.parsePacket()))
break;
delay(1000);
}
udp.read( sbuf, 81);
sbuf[packetSize] = '\0';
Spark.publish( gsprogname, sbuf);
udp.stop();
The Spark.publish
shows several datagrams are received at once, concatenated wrongly into one. UDP on the Spark Core is fundamentally broken.