Is there a way to force a "UDP client recieve timeout" [SOLVED]

Playing around with a transceiver and it works great, until it actually fails :wink:

It works by sending a UDP broadcast, and then it waits for a return.
However sometimes for a variety of reason the return might not happen.
These are the cases i want to timeout, because what happens right now both
in Unity 4 and 5 is that the entire Unity thread just becomes unresponsive.

Well basically it’s blocking the entire program until it receives a signal,
that is kinda silly.

I was originally looking to make a UDP listener, but without proper understanding
i so far only got a ā€œupdateā€ function working. Ideally i would have a listener just
checking for udp signals, but with my current knowledge or lack of the same,
that would just make a continuously blocking program.

Here is some code…

    public void updateUDPStatus()
    {
        packetData = "send this S1, returns status";     
        sendUDP(packetData);  // This is sendt to the UDP server, which responds with a status

        UdpClient receivingUdpClient = new UdpClient(returnPort);
        IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
        try{

// PROBLEM\BLOCKING LINE BELOW
            Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);// <--- THIS IS THE PART WHERE IT BLOCKS
// PROBLEM\BLOCKING LINE ABOVE

            String returnData = Encoding.ASCII.GetString(receiveBytes);
            myString = returnData;      
            for (int i = 0; i < myString.Length; i++)
            {
                if (myString[i] == 'S')
                {
                    int io = i+1;
                    updateLight(myString[io]);  // Do stuff with IO
                }
            }
            receivingUdpClient.Close();
        }
        catch ( Exception e ){
            Console.WriteLine(e.ToString());
        }
    }

Any suggestions ?

and if you suggest threading, well then I’m going to need a small example of threading,
never used it before.

the classes you are using are from the mono/.net framework, and not unique to unity.

These classes aren’t directly written to be multi-threaded, but instead intended to be used in a thread. The method ā€˜UdpClient.Receive’ naturally blocks, so you should spin up a thread to do this on, and exit the thread when it’s done.

I would do this in a Coroutine, where you start the coroutine, start the thread, perform the task in the thread, and back in the coroutine you just loop yield return null until the thread flags being finished.

Something like this:

    public IEnumerator updateUDPState()
    {
        bool finished = false;
        string myString;

        System.Threading.ThreadPool.QueueUserWorkItem(() =>
        {
            var packetData = "send this S1, returns status";
            sendUDP(packetData);  // This is sendt to the UDP server, which responds with a status

            UdpClient receivingUdpClient = new UdpClient(returnPort);
            IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            try
            {

                // PROBLEM\BLOCKING LINE BELOW
                byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);// <--- THIS IS THE PART WHERE IT BLOCKS
                // PROBLEM\BLOCKING LINE ABOVE

                string returnData = System.Text.Encoding.ASCII.GetString(receiveBytes);
                myString = returnData;
                receivingUdpClient.Close();
            }
            catch (System.Exception e)
            {
                Debug.LogException(e);
            }

            finished = true;
        });

        while(!finished)
        {
            yield return null;
        }

        //process data
        for (int i = 0; i < myString.Length; i++)
        {
            if (myString[i] == 'S')
            {
                int io = i + 1;
                updateLight(myString[io]);  // Do stuff with IO
            }
        }
    }

This doesn’t stall out the program, because it’s on another thread.

Of course, if Receive blocks indefinitely, this thread will sit hanging. If Receive doesn’t auto timeout, you can timeout yourself, by having a ticker in the while loop that checks how long you’ve been waiting.

Also, UdpClient should follow the .Net ā€˜Begin/End’ design, which means there should be a ā€˜BeginReceive’ method on the client to call instead of ā€˜Receive’ that will spin up the thread for you and return an AsyncResult object that you can check in the while loop.

I also noticed the ā€˜Console’ reference on there. I then looked at the UdpClient msdn page:

It appears you ripped this code directly from there.

First and foremost, you can’t use ā€˜Console’ in unity. You have to use Debug instead.

Another thing, you sometimes can’t just rip code straight from msdn. It’s really just for demo purposes, as well as this is actually mono and not .net, also unity sometimes throws a wrench into things because update and coroutine calls are intended to only take small fractions of time and not hold up the whole main thread.

What you should be is using those examples as guidelines to help you learn the object.

This code is ripped, as a part of a learning process.
I know about the console write, I’m using visual studio as development platform, since i
run the server from a console application and the client from unity.

Anyway…

Thank you for your for suggestion and judgement.

NEW EDIT ::

Found another solution…
after messing around, and reading more on MSDN, aparently they allready
made something for this :wink:

UDPclient.availbie so simply adding the if statement, does not lock up the thread
and does infact work great. This is not a continuing loop, but if it where
it might be a good idea to add a sleep to reduce cpu power.

anyway this is what i got working.

    // check for response ---
    void recieveStatus(char targetLetter)
    {

        UdpClient minUdpClient = new UdpClient(returnPort);
        IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
        try{
            if (minUdpClient.Available > 0)  // <----- THIS IS SEXY
            {
            Byte[] receiveBytes = minUdpClient.Receive(ref RemoteIpEndPoint);
            String returnData = Encoding.ASCII.GetString(receiveBytes);
            findData (returnData, targetLetter);
            minUdpClient.Close();
            } else {
                Debug.Log("NO DATA AVAILIBLE");  // uhhhh,  using Debug.Log,,
            }
        }
        catch ( Exception e ){
            Debug.Log(e.ToString());
        }
        minUdpClient.Close();
    }