Unix Programming - Grabbing several datagrams from a socket

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > September 2007 > Grabbing several datagrams from a socket





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Grabbing several datagrams from a socket
Spoon

2007-09-28, 7:30 am

Hello everyone,

Consider an internet datagram socket.
sock = socket(PF_INET, SOCK_DGRAM, 0);

Suppose I know there are more than one datagram waiting in the socket.
(For example, because I'm receiving 4000 packets per second, and I've
just woken up from a 10 ms sleep.)

It seems wasteful to make one system call per datagram I'm about to
recv(). On the other hand, the overhead from the system calls might be
negligible.

I think I could write:

uint8_t buf[PACKET_SIZE*N];
struct iovec iov;
for (int i=0; i < N; ++i)
{
iov[i].iov_base = buf + PACKET_SIZE*i;
iov[i].iov_len = PACKET_SIZE;
}

then call recvmsg().

If I don't set MSG_DONTWAIT, will recvmsg() block until N packets are
available?

If I do set MSG_DONTWAIT, and if there are 0 datagrams available, will
recvmsg return -1 with errno set to EAGAIN?

If I do set MSG_DONTWAIT, and if there are 0<K<N datagrams available,
will recvmsg return PACKET_SIZE*K with errno unchanged?

Final question: has anyone measured the overhead of calling recv() 10
times in a loop vs calling recvmsg() to greb 10 packets?

(My OS is Linux 2.6.22 if it matters.)

Regards.
Rainer Weikusat

2007-09-28, 1:24 pm

Spoon <root@localhost> writes:
> Consider an internet datagram socket.
> sock = socket(PF_INET, SOCK_DGRAM, 0);
>

[...]

> It seems wasteful to make one system call per datagram I'm about to
> recv(). On the other hand, the overhead from the system calls might be
> negligible.
>
> I think I could write:
>
> uint8_t buf[PACKET_SIZE*N];
> struct iovec iov;
> for (int i=0; i < N; ++i)
> {
> iov[i].iov_base = buf + PACKET_SIZE*i;
> iov[i].iov_len = PACKET_SIZE;
> }
>
> then call recvmsg().


[...]

> If I do set MSG_DONTWAIT, and if there are 0<K<N datagrams available,
> will recvmsg return PACKET_SIZE*K with errno unchanged?


No. Datagram sockets preserve message boundaries, and this means that
each call to a receive-routine will return exactly one message (in
absence of errors).
Spoon

2007-09-30, 7:38 am

Rainer Weikusat wrote:

> Spoon wrote:
>

Doh! I meant struct iovec iov[N];
[vbcol=seagreen]
>
> No. Datagram sockets preserve message boundaries, and this means that
> each call to a receive-routine will return exactly one message (in
> absence of errors).


If I understand correctly, recvmsg() could be used to "splice" a single
large datagram into several parts (one part per struct iovec). But it
can't be used to receive more than one datagram?

If this is correct, my question becomes: Is there a way to receive more
than one datagram in a single system call?

Regards.
Yakov

2007-09-30, 7:38 am

On Sep 30, 10:48 am, Spoon <root@localhost> wrote:
> Rainer Weikusat wrote:
>
>
>
>
>
> Doh! I meant struct iovec iov[N];
>
>
>
>
>
> If I understand correctly, recvmsg() could be used to "splice" a single
> large datagram into several parts (one part per struct iovec). But it
> can't be used to receive more than one datagram?
>
> If this is correct, my question becomes: Is there a way to receive more
> than one datagram in a single system call?


No (that is, not without introducing new syscall in the kernel).
But if you change UDP to TCP, you get the desired property
automatically.
Did you actually measure the overhead of the recv() syscall to begin
with ?

Yakov

Rainer Weikusat

2007-09-30, 1:24 pm

Yakov <iler.ml@gmail.com> writes:
> On Sep 30, 10:48 am, Spoon <root@localhost> wrote:

[...]
[vbcol=seagreen]
>
> No (that is, not without introducing new syscall in the kernel).
> But if you change UDP to TCP, you get the desired property
> automatically.


TCP is bytestream protocol, consequently, there is not way to 'receive
a datagram' with TCP. A successful receive will return some number of
bytes between zero (remote closed the connection) and the size of the
buffer which was passed to the syscall. Additionally, it is a reliable
protocol, which is not useful for realtime-applications (which I
figure 'Spoon' is writing about), because the data becomes useless
once the time when it would have been needed has passed (imagine a
local 10s power outage at some place where a router forwarding
telephone voice data sits: If data from this period is afterwards
retransmitted, the receiver would be ten seconds in the past relative
to the sender afterwards).
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com