Discussion:
Sending UDP packets at a specified rate
(too old to reply)
Spoon
2006-04-18 22:57:55 UTC
Permalink
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%?
Spoon
2006-04-19 12:30:11 UTC
Permalink
(Originally posted to comp.unix.programmer)
Post by Spoon
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
(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%?
purple_stars
2006-04-19 18:37:50 UTC
Permalink
Post by Spoon
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
(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.
Post by Spoon
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.
Post by Spoon
I suppose I could waste time in a busy loop, but I don't like that solution.
sure you could do that too.
Post by Spoon
Is there a (simple?) way to send 500-byte packets every 0.1 ms without
pegging the CPU to 100%?
using usleep(). cheers.
Rick Jones
2006-04-19 21:44:41 UTC
Permalink
Post by purple_stars
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...
Spoon
2006-04-20 09:04:12 UTC
Permalink
Post by purple_stars
Post by Spoon
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
(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.
Post by purple_stars
Post by Spoon
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.
Post by purple_stars
Post by Spoon
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.
purple_stars
2006-04-20 14:59:21 UTC
Permalink
[snip]
Post by Spoon
Post by purple_stars
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() :)
d***@webmaster.com
2006-04-20 16:25:01 UTC
Permalink
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
W***@lmco.com
2006-04-24 15:04:28 UTC
Permalink
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
Rick Jones
2006-04-24 17:28:55 UTC
Permalink
Post by W***@lmco.com
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?
Post by W***@lmco.com
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...
W***@lmco.com
2006-04-25 23:53:27 UTC
Permalink
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.
doina babu
2006-04-26 08:51:14 UTC
Permalink
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.
Ian Collins
2006-04-26 09:11:58 UTC
Permalink
Post by doina babu
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.
Continue reading on narkive:
Loading...