UDP packets not always sent out.
I've been struggling to try and figure out why Lemur (and also TouchOSC) don't always update when I sent out some OSC packets from Max.
I finally installed a packet sniffer on my Mac and discovered that in fact Max sometimes doesn't send the packets out. A [print] object
connected beside the [udpsend] object indicates that [udpsend] is certainly being called properly.
I'm not sure at all what's going on here but I'm wondering if there are known problems with the [udpsend] object in Max 5 (and Max 6, I tried both).
Thanks,
D
Interested to know about this as well.
I've had similar issues with a custom iOs application. I know that by definition UDP does not check if messages have been received but just throws data to the host like it just don't care.
It would be great to hear from the devs if it is just an inherent feature that some times packets are dropped or if it is an actual bug with the object.
In my case, it's not that packets are dropped (i.e, ignored by receiver) but that they don't sometime don't even get sent out (according to Wireshark)
Shot in the dark.. try inserting deferlow in front of udpsend.
Good shot but I already tried that yesterday.
Sometimes udpsend's internal queue can get over run.
Increase the maxqueuesize, it's in the help file.
-A
So I have tried some more experiments. I created patchers in both Max 5 and in PD that use a metro to send a cycle of messages (A to Z and then back to A again) over udp, one every 500ms. I also wrote a simple UDP Monitor for my iPad and watched the incoming messages and also ran my packet sniffer on the Mac.
I found two things of interest with both Max 5 and with PD.
1) Every now and then there would be a delay (typically 3-5 seconds) during which time nothing showed up on the iPad and then a clump of packets showed up together. No packets were lost (as I could see because of the A-Z pattern of messages).
2) Sometimes, after such a delay, some packets were in fact missing, typically two or three.
When I checked the packet sniffer on the Mac, the packets that were missing on the iPad did NOT show up in the sniffer.
So for some reason (and at this point I have no idea what's going on), sometimes packets are not even being sent out.
I have to assume that the [udpsend] on Max and PD are implemented differently (The Max version understands OSC but the PD version requires a [packOSC] object and so I'm left to wonder if there's something more fundamental going on.
Any ideas?
Thanks, Andrew, I had tried that yesterday but it didn't seem to help. Also, these packets are not very big and I assume that once they get sent out, the queue is emptying automatically.
Hi,
alternatively, you could try my network externals (see https://cycling74.com/forums/announce-the-sadam-library-version-2012-10-08 ). However, since they don't support OSC, you'd need to add the OSC formatting to your messages by hand, which (depending on the difficulty of your data structure) could be quite a painful process...
HTH,
Ádám
I looked quickly at your object but didn't know how to quickly create an OSC message at your object would accept. The OSC messages are very simple, just single messages, but right now I'm trying to figure out whether the problem is with Max (and PD) or whether there is something broken at a lower level, on two of my systems, which is also hard to believe,
If you can provide me with an example of how to send a simple OSC message though your object, I can at least run the tests again to see if there's any change in behavior.
Hi,
unfortunately I don't have an abstraction/object this time that would create binary-formatted OSC messages. However, for testing purposes, you can generate any OSC-formatted binary message using this small test patch:
HTH,
Ádám
Cute trick.
OK, I was able to modify my test to use your object and I'm seeing the same behavior, actually in some ways even worse. I saw several delays, some missing items in the sequences and at one point I started getting error messages in the Max window
sadam.udpSender: Can't send data to '192.168.0.187' on UDP port 8000
I'm not sure yet why it thought it couldn't send data out....in fact I'm wondering if that's somehow a clue as to what might be wrong.
Hi,
definitely a clue. Didn't you also get an error message on the rightmost outlet at the same time when you got the 'Can't send data...' stuff? (If not, you might need to enable the 'verbose' attribute of the object.) Could you please tell the error code as well?
Thanks,
Ádám
I didn't see any right most outlet --- not sure what you mean.
This is what I used
OK, typo. I meant 'leftmost'. Although the object has only a single outlet, so at the end of the day, it's the same... ;-)
I'm wondering the 'errno' values when you get the errors. It would be also interesting to see if you get 0 as errno at the time when your packages get dropped/delayed.
Thanks,
Ádám
dhjdhjdhj,
Have you tried sending your data to another computer running max?
Another shot in the dark but might be a way to see if it is actually the [udpsend ] object being unreliable or something on the receiving end.
I know that the sniffer should prove this wrong but have generally had good results communicating between laptops.
Just me 2p
Well, I just wrote and tested a simple command line application that sends a sequence of OSC messages out to my iPad where I'm monitoring the results.
Wireshark continues to indicate that some packets don't even get sent out and that fits with what I'm seeing (and not seeing) on the iPad.
So this would seem to have nothing to do with Max (which I suppose makes sense, it was hard to believe that udpsend was really broken) and there's something much more fundamental going on. I've unstalled my firewall (little snitch) and that made no difference either.
Very bizarre but I no longer consider this to be a Max issue.
Bummer!
Hi,
Another comment. If you get the error number, you might want to check up that error number on the internet (they are standard *NIX errno values, which you can access for example here: http://www.barricane.com/c-error-codes-include-errno ). My guess is that for each message that gets lost (in other words: each message that wouldn't show up in Wireshark) you'll get back a "can't send data..." message with an errno. I really hope that decoding the errno value will actually tell you the reason why some of your messages wouldn't be sent out.
Hope this helps,
Ádám
Adam, after removing little snitch I tried your version again, this time connecting the output to a [print].
I got 0 for a long time and then I started seeing the error
sadam.udpSender: Can't send data to '192.168.0.187' on UDP port 8112
and an output value of -1
However, I didn't immediately stop the test and after about 15 seconds, the error message stopped being generated and it started transmitting again properly.
I'm not sure if your source code is available --- what kinds of things cause you to send out that "Can't send data" error message?
This is just very strange.
OK, this was an ugly bug that I just fixed. For some weird reason it was sending -1 instead of the actual errno value, but that's no longer the case. Please download the library again for the fixed version.
The sadam Library is a weird project in the sense that, although it's free and the license is allowing the end-users to use the objects for commercial purposes (except for one single object which is using a GPLv2 code, therefore that object is also GPL-ed and it's source code is revealed), it is closed-source. Therefore, the source code of these objects is not available. This has to do mainly with my personal convictions...
With that said, the "can't send data..." messages are generated when the following code line returns with a negative value:
result = sendto ( socketDescriptor, ( const char * ) iterator, size, 0, ( const struct sockaddr * ) & address, sizeof ( address ) );
where result
is a long
, socketDescriptor
is either an int
(Mac OS) or a SOCKET
(Win32) representing the socket used for data transmission, iterator
is an unsigned char *
that points to a pre-allocated array of characters in the memory containing the data to send, size
is an unsigned long
that represents the size of the previously mentioned array and address
is a struct sockaddr_in
that holds the address of the remote address where the messages should be sent.
The socketDescriptor
is created with a call to
socketDescriptor = socket ( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
and is bound to a port before executing any sendto messages with a call to
bind ( socketDescriptor, ( const struct sockaddr * ) & address, sizeof ( address ) );
Additionally, on Windows, I start up the Winsock stuff with a call to WSAStartup ( MAKEWORD(1, 1), & wsaData ) );
before anything else.
This is not exactly the source code (error checking etc. is omitted here as well as some tricks to make things smaller but less readable), but this should give you a complete picture of what's happening under the hood.
Hope this helps,
Ádám
Are you creating a local network through built-in wifi? Recently I moved to using a airport express after all sorts of stability issues, including loosing connection. I have just started working with touch-osc and used it so far in two performances, without any issues. In my case however data is sent in one direction only. Conclusion for me anyway is to avoid using built-in wifi (2008 unibody).
OK ---- I have now done enough experiments that I'm pretty sure that the issue is related to wireless connections.
I tried Miguel's suggestion and set up a Max patcher on my laptop to receive the test messages from my desktop machine. Both machines are on the same subnet, connected by Ethernet. All packets were received perfectly fine with no obvious delays.
I then disconnected my laptop from Ethernet and reconnected through wifi. Desktop still connected to LAN via ethernet.
This time, reception of packets was slightly irregular and very occasionally a packet did not arrive. They didn't get lost as often as on the iPad but it happened!
So it really looks like UDP is not reliable over wireless, even in a small environment where all the devices (including the router) are physically close. This is disappointing.
@jvkr
I've used Lemur successfully to send commands to Max for some time but typically these were fader movements and even if one packet was getting lost occasionally, it wouldn't really have mattered. The problem is only noticable when I go the other direction and I'm sending TEXT labels and sending them just once. I might try adding in a hack where I store each outgoing text value in a [pv] and send it out twice over a period of a second but what a pain.
Siska, I updated your library and the only non-zero error number I saw occasionally was -64. But I didn't see that error when packets were being missed occasionally so that seems more like a more generally connectivity problem.
Thanks to everyone for suggestions and feedback. This has been quite illuminating if not disappointing.
Hi,
this sounds really weird. Standard error numbers (reported by 'errno', whose value in my code is saved into an int
just after calling sendto
) are supposed to be positive numbers. So I really can't imagine what's happening there. However, if for some reason this is actually the positive value 64, then it corresponds with the 'Host is down' error, according to Apple's version of errno.h. Since UDP doesn't really keep track of the packages, this doesn't make too much sense, though. I don't know how much this helps you after all...
Best,
Ádám
PS: Feel free to call me on my first name (which is Ádám).
PS2: It might also happen that there's something wrong with your wireless router. I participated on several concerts where we had to do the rehearsals in small rooms with only the in-house wireless network available. Although we usually send a load of UDP and TCP messages, most of the time we don't experience the problems that you described above.
@Ádám ---- sorry --- from your username, I assumed your first name was "Siska"
I don't believe it's the router because (a) I've done these experiments with two separate routers and (b) I also tested with Adhoc connection between laptop and iPad. It seems to be a general problem with UDP over wifi.
I don't know how you're using UDP for your rehearsals....having a couple of packets get lost when you're doing continuous change (e.g, fader movement) won't matter but when you're sending a single UDP packet to change the text of a label and that packet gets lost, it's a different problem.
I just built a "SendTwice" object that stores an incoming value in a private [pv] and then forwards it immediately and then again after a delay. Inserting those into my object that sends various text messages to Lemur has "solved" the problem sufficiently that I can move on.
What a pain, though.
I've seen problems like this with encrypted wireless networks.
The way I currently have my stage wireless network set up is to hide the network, only allow connections by MAC address, and turn encryption and all security off.
-A
Andrew, my stage wireless network is setup exactly that way as well, no encryption, no passwords, using MAC address to allow only my iPads and iPhone to connect. My laptop has an ethernet connection so only the devices are wireless.
One of my business partners who has just been experimenting with sending audio over UDP has told me he has seen exactly the same problem with UDP packets getting dropped occasionally. It does seem to be just "what you get" with UDP.
If my SendTwice hack doesn't suffice, I'll considering building a little TCP-UDP "echoer" for my iPad. This would allow me to send TCP packets from Max to the iPad and then echoer would resend them to localhost over UDP, thereby getting them to Lemur. I'm trying to prepare for several upcoming tours (which is what got me started with Lemur to replace one of my physical control surfaces in the first place) so I really don't want the distraction. Thank goodness Max makes it so easy to throw in hacks to work around issues!
Hi,
now that you mentioned it, you're right. Probably we didn't notice the drops with continuous data. And you're right, we never use UDP to send messages where it is important to avoid dropped packages. For that purpose, we've always used TCP (either my own TCP objects or the net.tcp.*
MXJ-classes).
Hope that helps,
Ádám
Hi all,
@dhjdhjdhj is it only the ipad you need to connect?
I recently finished a project were I was sending data to 50 ipod touches. It was basically a glorified metronome to keep 50 brass players in sync (reading from a dead tree score) as they were distributed all over the place at a mall thus making it impossible for the piece to be conducted. I had the same issues you describe, packages being lost now and then. I tried something similar to what you describe (re-sending each message more than once) but this resulted in a lot of jitter. Each performer was getting all the messages but not in sync. I haven't done any strain tests after the concert to see how many devices can be used reliably but just pointing out that flooding the network might create other issues. Probably not a problem for you if you are only connecting the one ipad.
@Adam got your updated library today and love the new feature that gets the IP of the remote client! great work.
I will look at TCP objects but assume that at this stage that would only work with other computers? it would be interesting if LEMUR and TouchOSC added the option to use TCP as well.
cheers lads
Yes, I just want to send information reliably to Lemur. I wish Liine could be persuaded to support TCP as well as UDP.
I looked into building a little background app on the iPad that would receive TCP packets from an external connection and forward the data to 'localhost' in UDP packets. I figured that Lemur could be persuaded to listen to 'localhost'
However, the problem is that iOS doesn't want to allow network apps to continue running in the background so unless I can figure a way around that, I'm stuck.
Having sort of the same issue.
Any new solutions in the last 4 years?
None that I'm aware.
For what its worth,
I am not using Max/Msp anymore, and I wrote a Java application that sends my OSC.
The problem I have been having with UDP packet lose was occurring when I send many large bundles very fast (up to 500 bundles of 1400 bytes each, in 2 milliseconds).
Lemur would simply not receive some of the packets, although I was connected to my iPad directly via USB tethering.
The weird thing, is that I made the same test in local host, with an OSC server running in NodeJS, and I still got the packet lose.
The second weird thing is that using Wireshark, I saw that the packets were sent, but the OSC server was not receiving them.
This makes me wonder, if there is some common OS X and iOS, issue (or feature) where a maybe there is a limited Queue of packets that can wait to be read by an application which listens on a UDP socket. And sometimes this queue is overfilled and packets are dropped.
Only solution I see now is using TCP.
Since Lemur still does not support TCP,
I intend to develope my UI as a hybrid web application, which will run on iPad natively (using Ionic or React Native), and will use TCP.
There is nice Web UI library (Open-Source, Javascript) called NexusUI with similar UI components as Lemur.
Good luck to us all
HEPi
In Java this is addressed via the relevant methods of DatagramSocket:
DatagramSocket.setReceiveBufferSize() and
DatagramSocket.setSendBufferSize()
With these adjusted properly I have never had issues with lost datagrams. YMMV