Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C sendmsg() no buffer space available

Tags:

c

I'm not an expert in C programming, but I'm trying to write a fairly simple program using sendmsg() and recvmsg() to send a message between a client and a server (both are on the same machine, so basically I'm sending a message to localhost).

After initialising the required structures (as in the iovec and the msghdr) and succesfully connecting the client to the server, my sendmsg() call fails with "no buffer space avaliable" errno.

This is what linux man reports about this type of error:

The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but maybe caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)

I looked around on the Internet and as a result I found out that sendmsg() is not widely used, and nobody could relate with this type of error. The only useful advice I found was to check a possible excess of open sockets, but again I always close EVERY socket I create.

So I'm stuck, basically because being quite the noob I don't know exactly where to look to fix this kind of problem.

If anybody knows how to proceed, it would be great. (And please don't tell me not to use sendmsg(), because the whole purpose of my work is to understand this syscall, and not send a message to myself)

Here's the code I've written so far on pastebin: client and server

--SOLVED--

Thank you very much. I've been able to solve the problem and I fixed other mistakes I made, so here's the functioning code for sendmsg() and recvmsg() working message-passing: Client and Server

like image 796
xHawk Avatar asked Oct 10 '12 13:10

xHawk


3 Answers

As others have pointed out, iovlen should be 1. But also, you want to zero out mh before initializing some of its fields since you're probably sending in garbage in the uninitialized fields and the syscall gets confused. Also, it doesn't really make sense to set msg_name and msg_namelen since you're connected and can't change your mind about where to send the data anyway.

This is what works for me in your client code:

/* The message header contains parameters for sendmsg.    */
memset(&mh, 0, sizeof(mh));                                                                                                                                                                                                                                                                          
mh.msg_iov = iov;
mh.msg_iovlen = 1;

printf("mh structure initialized \n");
like image 167
Art Avatar answered Nov 16 '22 02:11

Art


The msg_iovlen field contains the number of elements in the iov array, not its size in bytes.

The system interpreted the following uninitialized memory as iov elements, ended up with a packet that is larger than the socket buffer space available, and thus refused to send the data.

like image 38
Simon Richter Avatar answered Nov 16 '22 03:11

Simon Richter


Okay, so in your code I found this:

mh.msg_iovlen = sizeof(iov);

Which sets the msg_iovlen member to the size of struct iovec. But the documentation says this about this field:

size_t msg_iovlen; /* # elements in msg_iov */

So your code is wrong, it tells sendmsg() that it's going to send way more elements than you actually initialize.

like image 2
unwind Avatar answered Nov 16 '22 03:11

unwind