Mackhdo
Mackhdo

Reputation: 110

Need a better way to wait between send and receive,UDPclient

Here's my trouble:

I have a udp class that allow me to send and receive data from a gameserver.

But i found that the server allow only one request per 500ms per client. so if i send two request in a row, the server respond only to the first one, and i have no way to know that i won't get the second answer.

So i made a Mutex to protect the send part, when i send data, i use a thread to block the mutex 500ms.

This class is used by thread, that's why i use mutex.

But this doesn't work really good, sometime the receive get stuck.

I just want to know if someone have a better way to do this.

Thank you and sorry for my english.

EDIT: I can't use tcp protocol, i need to do this with udp. I also need an optimal way, i need to get the receive data asap to the viewform. I watch every single topic on the net i found on udp and threading, but don't find this particular case.

Upvotes: 1

Views: 2604

Answers (3)

unholysampler
unholysampler

Reputation: 17321

If you know you can only send with some frequency, why not send calls blocking. And then sleep for the required time.

class UDP {
  int _lastTime = 0;
  int MIN_DELAY = 500;

  public void send() {
    lock(this) {
      int duration = now() - _lastTime;
      if (duration < MIN_DELAY) {
        sleep(MIN_DELAY - duration);  
      }
      realSend();
      _lastTime = now();
    }
  }
}

Upvotes: 1

chezy525
chezy525

Reputation: 4174

As others have pointed out, it can't be assumed that a UDP message will be delivered. This is probably causing the hanging of your code on the receive. Maybe simply setting the Socket's ReceiveTimeout will be good enough for you're application.

Or you could setup a (somewhat more complex) method of queuing messages to send, only sending one every 500ms, and retrying them after a certain amount of time until you've gotten a response. If I were going this route, I'd design around these general points:

  • Use Asynchronous UDP.
  • Build a struct/class for the actual information to send/receive (say, MsgObject), Including information about the last time it was transmitted.
  • Use this MsgObject as your AsyncState object.
  • Manage a thread-safe queue/list of all active MsgObjects. i.e. messages that have been requested to send, but no response has been received.
  • Have a simple timer to check the queue/list periodically (no more frequently than every 500ms in your case) to see if there's a new message to send or one that needs to be resent.
  • In the asynchronous receive function, remove the MsgObject that received the response from the queue/list.

Upvotes: 0

Dan Bryant
Dan Bryant

Reputation: 27495

With UDP, you should never assume that you will get a response to any given message you send. You should also not assume that the message will actually be received or that multiple messages will be received in the same order you send them. That's why UDP is really only suited to protocols that can tolerate loss of information. If you want to maintain integrity, you need to allow for retries, at which point you probably would've been better off using TCP (assuming you had a choice in the matter.)

Without more information on the details of the protocol, it's hard to recommend a good solution. If it's a simple 'status poll' style of message, one option is to simply send the polling messages at a fixed interval and handle the responses as they arrive, ignoring any relation the responses might have to the messages being sent.

Upvotes: 1

Related Questions