Sending UDP packets at a specified rate

Hello,

I am trying to understand how to write a simple network program that
sends UDP packets at a specified rate.

For example, let's say I want to send 500-byte packets at 40 Mbit/s

This means I want to send one packet every 0.1 ms

In my mind, the naive way to do that would be to write:

(pseudo code...)

while (1)
{
  send(500-byte UDP packet);
  sleep(0.1 ms);
}

But I don't think any of the sleep functions (nanosleep?) will let me
sleep for such a short period, will they?

Maybe I could send 10 packets, then sleep 1 ms? That might solve the
sleep problem, but my traffic would be very bursty.

I suppose I could waste time in a busy loop, but I don't like that solution.

Is there a (simple?) way to send 500-byte packets every 0.1 ms without
pegging the CPU to 100%?
0
Spoon
4/18/2006 10:57:55 PM
comp.unix.programmer 10818 articles. 0 followers. kokososo56 (349) is leader. Post Follow

11 Replies
1934 Views

Similar Articles

[PageSpeed] 41

(Originally posted to comp.unix.programmer)

Spoon wrote:

> I am trying to understand how to write a simple network program that
> sends UDP packets at a specified rate.
> 
> For example, let's say I want to send 500-byte packets at 40 Mbit/s
> 
> This means I want to send one packet every 0.1 ms
> 
> In my mind, the naive way to do that would be to write:
> 
> (pseudo code...)
> 
> while (1)
> {
>   send(500-byte UDP packet);
>   sleep(0.1 ms);
> }
> 
> But I don't think any of the sleep functions (nanosleep?) will let me
> sleep for such a short period, will they?
> 
> Maybe I could send 10 packets, then sleep 1 ms? That might solve the
> sleep problem, but my traffic would be very bursty.
> 
> I suppose I could waste time in a busy loop, but I don't like that solution.
> 
> Is there a (simple?) way to send 500-byte packets every 0.1 ms without
> pegging the CPU to 100%?
0
Spoon
4/19/2006 12:30:11 PM
Spoon wrote:
> Hello,
>
> I am trying to understand how to write a simple network program that
> sends UDP packets at a specified rate.
>
> For example, let's say I want to send 500-byte packets at 40 Mbit/s
>
> This means I want to send one packet every 0.1 ms
>
> In my mind, the naive way to do that would be to write:
>
> (pseudo code...)
>
> while (1)
> {
>   send(500-byte UDP packet);
>   sleep(0.1 ms);
> }
>
> But I don't think any of the sleep functions (nanosleep?) will let me
> sleep for such a short period, will they?

you could use usleep() but the timing won't be exactly right on a
non-real time os unless maybe you use a hardware timer and create an
interupt every X amount of time.

> Maybe I could send 10 packets, then sleep 1 ms? That might solve the
> sleep problem, but my traffic would be very bursty.

if that's an option it doesn't even matter if it's real time, use
usleep() that's what you are looking for.

> I suppose I could waste time in a busy loop, but I don't like that solution.

sure you could do that too.

> Is there a (simple?) way to send 500-byte packets every 0.1 ms without
> pegging the CPU to 100%?

using usleep().  cheers.

0
purple_stars
4/19/2006 6:37:50 PM
> you could use usleep() but the timing won't be exactly right on a
> non-real time os unless maybe you use a hardware timer and create an
> interupt every X amount of time.

and, just as with nanosleep(), not all systems that offer a usleep()
actually have that fine a granularity. To wit, from the usleep manpage
under HP-UX 11i:

      Implementations may place limitations on the granularity of
      timer values. For each interval timer, if the requested timer
      value requires a finer granularity than the implementation
      supports, the actual timer value will be rounded up to the next
      supported value.

rick jones
-- 
oxymoron n, commuter in a gas-guzzling luxury SUV with an American flag
these opinions are mine, all mine; HP might not want them anyway... :)
feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...
0
Rick
4/19/2006 9:44:41 PM
purple_stars wrote:

> Spoon wrote:
> 
>>I am trying to understand how to write a simple network program that
>>sends UDP packets at a specified rate.
>>
>>For example, let's say I want to send 500-byte packets at 40 Mbit/s
>>
>>This means I want to send one packet every 0.1 ms
>>
>>In my mind, the naive way to do that would be to write:
>>
>>(pseudo code...)
>>
>>while (1)
>>{
>>  send(500-byte UDP packet);
>>  sleep(0.1 ms);
>>}
>>
>> But I don't think any of the sleep functions (nanosleep?) will let me
>> sleep for such a short period, will they?
> 
> you could use usleep() but the timing won't be exactly right on a
> non-real time os unless maybe you use a hardware timer and create an
> interupt every X amount of time.

The man page for usleep in Linux states:

   This function is obsolete. Use nanosleep(2) or setitimer(2) instead.

>> Maybe I could send 10 packets, then sleep 1 ms? That might solve the
>> sleep problem, but my traffic would be very bursty.
> 
> if that's an option it doesn't even matter if it's real time, use
> usleep() that's what you are looking for.

I'll give nanosleep() a try.

>> I suppose I could waste time in a busy loop, but I don't like that solution.
> 
> sure you could do that too.

But I would hog the CPU even though I only need 2-3% of it on average...

Ugly.
0
Spoon
4/20/2006 9:04:12 AM
Spoon wrote:
> purple_stars wrote:
[snip]
> > if that's an option it doesn't even matter if it's real time, use
> > usleep() that's what you are looking for.
>
> I'll give nanosleep() a try.

i learned something too, i didn't know there was such a thing as
nanosleep() :)

0
purple_stars
4/20/2006 2:59:21 PM
The easy way to do it is just to keep track of the amount of bandwidth
you are using, and if it gets to high, sleep a bit before you send the
next bit.

If you are operating in contexts where you can't sleep, then just keep
a linked list of packets you need to send. Send them as appropriate.

For example, your send logic can go like this:

1) Is bandwidth usage high? If not, go to step 4.

2) Are there too many packets queued, if yes, return an error.

3) Queue the packet for later, return.

4) Is the bandwidth usage low and there are packets queued? If so, send
some of them and update the bandwidth estimate.

5) If we emptied the queue, send this packet (updating the bandwidth
estimate) and return. If not, queue this packet and return.

DS

0
davids
4/20/2006 4:25:01 PM
You may find that the nanosleep function uses a 10 ms. precision, such
that the smallest delay such as 1 ms. takes at least 10 ms.

You can work around this limitation by tracking the actual sleep time
and feeding any excess sleep time into the next delay calculation.
Gettimeofday returns very accurate time information.  This is how I
solved this very problem.  

Bill Lindquist

0
William
4/24/2006 3:04:28 PM
William.Lindquist@lmco.com wrote:
> You may find that the nanosleep function uses a 10 ms. precision,
> such that the smallest delay such as 1 ms. takes at least 10 ms.

> You can work around this limitation by tracking the actual sleep
> time and feeding any excess sleep time into the next delay
> calculation.

Don't you still end-up with bursts as the excess sleep time becomes no
sleeps for a while?

> Gettimeofday returns very accurate time information.  This is how I
> solved this very problem.

Careful there - I have seen - in the past anyway - gettimeofday only
increment by "large" chunks on some platforms - old Irix comes to mind
- I think it was an issue for SPECweb96 benchmarking.  And just about
any "gettimeofday" replacement under Windows may only increment in 10
ms chunks. (eg glib g_get_current_time() and its use of
GetSystemTimeAsFileTime())

When one doesn't need actual wall-clock time, going with something a
bit more platform-specific - at least for measuring "time" may be
useful/accurate/precise.  gethrtime() on those platforms which have
it, or something along those lines.  It doesn't solve the problem of
getting short sleep times, but it will tend to allow much finer
granularity of "time" measurement.

rick jones

I'm always confusing accuracy and precision

If one has a multiple CPU system, or even multiple systems on the
network, one could I suppose "sacrifice" one CPU to sit and spin
watching time pass and "chime" to affect the short timeouts by sending
messages to the other processes which wanted to have short timeouts
but not sit and spin.  Probably still burn a lot of cycles, but
perhaps not as many as having everyone spinning

-- 
No need to believe in either side, or any side. There is no cause.
There's only yourself. The belief is in your own precision.  - Jobert
these opinions are mine, all mine; HP might not want them anyway... :)
feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...
0
Rick
4/24/2006 5:28:55 PM
Gettimeofday is much more accurate then usleep (using IRIX 6.5.4 and
LINUX).  And there is no guarantee that the process will be immediately
restarted if other processes are competing.

Since usleep never returned to me in less than 10 ms. I adjusted the
delay time on the next iteration to compensate.  This causes some
acceptable burstiness.  So I might ask for a 5 ms. delay, get 10 ms.
and skip the delay the next iteration.  Overall the throughput gets me
what I want.

Otherwise, I would usleep for 5 ms. and delay 10 ms. each iteration
halving my throughput.

0
William
4/25/2006 11:53:27 PM
or you could use the "select" system call with all fields empty except
for the timeout. timeout is of struct timeval* type, so you could put
there as many/few usec you want.

0
doina
4/26/2006 8:51:14 AM
doina babu wrote:
> or you could use the "select" system call with all fields empty except
> for the timeout. timeout is of struct timeval* type, so you could put
> there as many/few usec you want.
> 
The minimum timeout for select is still limited by the system tick.

-- 
Ian Collins.
0
Ian
4/26/2006 9:11:58 AM
Reply: