Networking Forums  

Go Back   Networking Forums > Networking Newsgroups > Linux Networking

Grabbing several datagrams from a socket

Reply
 
Thread Tools Display Modes
  #1  
Old 09-28-2007, 12:32 PM
Default Grabbing several datagrams from a socket



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.


Spoon
Reply With Quote
  #2  
Old 09-28-2007, 02:18 PM
Rainer Weikusat
Guest
 
Posts: n/a
Default Re: Grabbing several datagrams from a socket

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).
Reply With Quote
  #3  
Old 09-30-2007, 09:48 AM
Spoon
Guest
 
Posts: n/a
Default Re: Grabbing several datagrams from a socket

Rainer Weikusat wrote:

> Spoon wrote:
>
>> 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;


Doh! I meant struct iovec iov[N];

>> 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).


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.
Reply With Quote
  #4  
Old 09-30-2007, 11:47 AM
Yakov
Guest
 
Posts: n/a
Default Re: Grabbing several datagrams from a socket

On Sep 30, 10:48 am, Spoon <root@localhost> wrote:
> Rainer Weikusat wrote:
> > Spoon wrote:

>
> >> 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;

>
> Doh! I meant struct iovec iov[N];
>
> >> 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).

>
> 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

Reply With Quote
  #5  
Old 09-30-2007, 05:12 PM
Rainer Weikusat
Guest
 
Posts: n/a
Default Re: Grabbing several datagrams from a socket

Yakov <(E-Mail Removed)> writes:
> On Sep 30, 10:48 am, Spoon <root@localhost> wrote:
>> Rainer Weikusat wrote:


[...]

>> 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.


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).
Reply With Quote
Reply

Tags
datagrams, grabbing, socket

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT. The time now is 09:45 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.