Sending blobs and other feature using a udp sender

Hi all,
I extended the udpSender /udpReceiver addons examples, in order to send Large sum of information between applications. What I send (which is nothing other than blobs) has the following format:

The basic parts are:
type [/b] blob_id [/b] features [/b] Polyline [/EOM]
where:
type = a 4-letter description of the blob that will follow (i.e. “blob”)
blod_id = an integer
features = 6 significant points of the blob
Polyline = the whole blob

Also:
the features and Polyline are basically a sequence of points. These are of the form:
x1 | y1 [/p] x2 | y2 [/p] … xN | yN [/p]
notice that there is an extra [/p] at the very end of these points

In the receiver end , i use ofSplitString() to

  1. separate the number of messages ( I look for [/EOM] terminator)
  2. for every msg, I split the 4 parts of the stream (type, blob_id, features, polyline)
  3. for every part of stream, I process it differently (since they are of different nature).

Now to max out my custom example , on a mousePress event at the senders end I randomly generate 10 blobs of variable number of points (100 to 1500 points :slight_smile: . So I send 10 of the above and indeed a blob as udp message may have length up to 38kBytes… As you can imagine 10 of them may go up to 380kBytes of data that needs to be send. The receiver reads 1000000 bytes per read - and it does not look like it has been maxed out (ever in the following examples).

Now running the examples , if I click just once in the sender, 10 blobs will be sent and received fine at the far end. The sender runs the random blob generator , converts everything to a string and sends the UDP message in a for loop - so everything is serialised and all 10 messages must be leaving the sender correctly.

If however I repeatedly click on the mouse a few times (say 4-5 times) the message will not arrive in full at the receiver. Basically, Individual blobs WILL arrive intact at the receiver, but some of the 10 blobs will never be received. Indeed, the latest blob that will arrive is not the last that was sent (ie the 10th) , but any weird combination. For example the 1st 4 messages may arrive each as a separate udpManager::Receive() call. Or the 1st 8. Also the 1,4,7 and 10th may arrive. so again not all of them will be received - only a few, but not the 1st only or the last ones. randomly picked ones (!)

I would appreciate it, If you could take a look:
the ofApp.* of the sender is http://pastebin.com/wpjmxUmh
the ofApp.* of the receiver is http://pastebin.com/TzzGFsgJ

could it be that some data get overwritten in the receiver buffer? If that was the case I’d expect some parsing error to occur and to send an error msg - but I don’t see any error.
do data arrive in mixed up order and thus the splitting could get mixed up? Again I would expect some error in the parser - but I don’t see any.
Since every blob is received in a separate message it means that some whole messages are being dropped. Possibly in the buffer because a next one arrives before the previous buffer has been read in by the application. Should I receive the data in a separate thread from the one where they get processed? Is there a way to be notified if a previous buffer has been discarded at the time of reading from the udp buffer? should I switch to tcp protocol?

in the examples you’ll also see that a “mark” instead of a “blob” may be send. It is of the form:
type [/b] mark_id [/d] centroid [/EOM]
type and mark_id are similar to blob case, and centroid is just a single point.
By clicking with the left button in the sender window you get to send blobs, and by right clicking you get to send marks. Just quickly and repeatedly left clicking should be enough to generate the error. I

thank you in advance for your help.

in the end , I implemented the receiver in 2 threads. the main thread that does the processing, and another that reads constantly (in non-blocking mode) the udp buffer. if there is a new udp message, it is appended in a vector and when the main thread asks for data , this vector is passed over.

As an overkill, I even implemented double buffering. So I instantiate 2 vectors and every time a vector is passed on to the main thread ptrs to the 2 vectors are swapped which is a faster operation compared to copying the vector to the main thread.

The whole thing seems to work now. I guess udp buffers were completely dumped since the application was not read fast enough from the buffer (because of the processing).

I do have a few questions however about programming choices and would like your opinion on them. my udpThreadedReceiver.h looks like

class UdpThreadedReceiver: public ofThread
{
public:
    UdpThreadedReceiver();

    void start();

    /// Signal the thread to stop.  After calling this method,
    /// isThreadRunning() will return false and the while loop will stop
    /// next time it has the chance to.
    void stop();

    /// Our implementation of threadedFunction.
    void threadedFunction();

    ///CAUTION: should ONLY be accessed from within a locked mutex environment
    void swapPts(vector<string>*& p1, vector<string>*& p2);

    ///the pointers to double buffering for UDP -
    ///ONLY USE THESE to access B1,B2 buffers!
    vector<string>* loadingBuffer , *processingBuffer;
private:

    ofxUDPManager udpConnection;
    //NO ONe is supposed to accesses these directly. only through pointers
    vector<string> B1 , B2;
};

so the 2 vectors are declared in the threaded class. the 2 ptrs to vectors are also only declared in this class. Indeed one should access these vector Only from the 2 pointers. However, having B1 and B2 there might tempt someone to use these. Is there a better way to declare these 2 vectors?
For a example, I read that I could only declare the pointers and instantiate the vectors in the constructor as :

loadingBuffer = new vector(size);
processingBuffer = new vector(size);

But this is confusing and ugly (what sort of “size” is this that I have to set?). I read something about using “unique_ptr”. I have not used that ever and don’t really know it. How could that help here? IS there any other way to hide completely the B1 and B2 automatic variables?

Another points is the fact that the swapPts() function is also declared in the udpThreadedReceiver class. It is a requirement that the pointer swaping needs to take place when the thread mutex is locked to avoid segfaults. I wonder if there is a good reason to harden the security and add an “if” statement in the swapping to avoid swap if the mutex is not locked. is there a point in doing that? Is there a method “bool ofThread::isMutexLocked()” ?

thanks!

While what you are describing is completely feasible, rather prefer to add a layer of abstraction using OSC, that defines a good way to encapsulate the message, and separate the arguments and mark a type for them, and implements a buffer of pending messages.

I recently used 4 kinects in two mac minis capturing up to 6 contours per kinect, to be sent to a receiver machine that handles the reception and interaction without problems. Uno think that may help is simplify the polyline to minimize the amount of points being send trough the network.

hi drakko,
I am using OSC already and wanted to move away from this. The reason is exactly that I could not send large contrours - and I want the extra detail. Indeed when I tried to send the full polylines with osc without simplification, the receiver end would crash. see ofxOscSender OutOfBufferMemoryException

so osc is not ideal for me.