Sendto on Tru64 returns ENOBUF
I am currently running an old system on Tru64 that includes many UDP sockets using the sendto () function. Sockets are used in our code to send messages to / from various processes, and then eventually to a thick client application that is connected remotely. Sometimes the fat client socket gets stuck, this can cause some of these messages to be generated. My question is how to determine the current buffer size and how to determine the maximum message buffer. The code below provides a snippet of how I set up the port and use the sendto function.
/* need to adjust the maximum size we can send on this */
/* as it needs to be able to cope with the biggest */
/* messages we send */
lenlen = sizeof(len) ;
/* allow double for when the system is under load */
int lenlen, len ;
lenlen = sizeof(len) ;
len = 2 * 32000;
msg_socket = socket( AF_UNIX,SOCK_DGRAM, 0);
result = setsockopt(msg_socket, SOL_SOCKET, SO_SNDBUF, (char *)&len, lenlen) ;
result = sendto( msg_socket,
(char *)message,
(int)message_len,
flags,
dest_addr,
addrlen);
Note. We put this app on Linux and the problem doesn't seem to show up there.
Any help would be greatly appreciated.
Hello
a source to share
The size of the UDP send buffer is different from TCP - it limits the size of the datagram. Stevens Quote UNP Vol. 1:
... a UDP socket has a send buffer size (which we can change with the socket optionSO_SNDBUF
, section 7.5), but that is just the upper limit of the maximum size UDP datagram that can be written to the socket. Returns if the application writes a datagram that is larger than the socket's send bufferEMSGSIZE
. Because UDP is unreliable, it doesn't need to keep a copy of the application data, and it doesn't need the actual send buffer. (Application data is usually copied into some form of kernel buffer because it passes the protocol stack, but this copy is discarded by the data layer after the data is transferred.)
UDP just adds an 8 byte header and sends the datagram to the IP. IPv4 or IPv6 adds a header, identifies the outgoing interface by performing a routing function, and then adds the datagram to the output queue (if it fits in the MTU) or fragments the datagram and adds each chunk to the output queue. If the UDO application sends large datagrams (for example, 2000 byte datagrams), the fragmentation is much more likely than TCP. because TCP breaks application data into MSS-sized chunks, which is unmatched by UDP.
A successful return fromwrite
a UDP socket tells us that either the datagram or all of the datagram fragments have been added to the output queue. If there is no room in the queue for a datagram or one of its fragments,ENOBUFS
often returns to the application.
Unfortunately, some implementations do not return this error, providing the application with no indication that the datagram was discarded without even being submitted.
The last footnote needs attention - but it looks like Tru64 has this error code listed on the page .
The correct way to do this is to queue your outstanding messages in the application itself and carefully check the return values errno
after each system call. This still does not guarantee delivery (since UDP receivers can drop packets without notifying the senders). Make sure the UDP packet counters are dumping netstat -s
on both sides, see if they go up. There is no way to do this other than switching to TCP or implementing your own timeout / ack and relay logic.
a source to share
You should probably use some kind of congestion control to avoid network congestion. The easiest way to do this is to use TCP instead of UDP.
On Linux, it solves less because UDP sockets wait on the local network interface queue on Linux (unless you set them non-blocking). However, with any operating system, if the redundant queue is not on the local system, the package will be silently disabled.
a source to share