What's the practical limit on the size of single packet transmitted over domain socket?
There are a number of factors which will determine the maximum of size of a packet that can be sent on a Unix socket:
The
wmem_max
socket send buffer maximum size kernel setting, which determines the maximum size of the send buffer that can be set usingsetsockopt (SO_SNDBUF)
. The current setting can be read from/proc/sys/net/core/wmem_max
and can be set usingsysctl net.core.wmem_max=VALUE
(add the setting to/etc/sysctl.conf
to make the change persistent across reboots). Note this setting applies to all sockets and socket protocols, not just to Unix sockets.If multiple packets are sent to a Unix socket (using SOCK_DATAGRAM), then the maximum amount of data which can be sent without blocking depends on both the size of the socket send buffer (see above) and the maximum number of unread packets on the Unix socket (kernel parameter
net.unix.max_dgram_qlen
).Finally, a packet (SOCK_DATAGRAM) requires contiguous memory (as per What is the max size of AF_UNIX datagram message that can be sent in linux?). How much contiguous memory is available in the kernel will depend on many factors (e.g. the I/O load on the system, etc...).
So to maximize the performance on your application, you need a large socket buffer size (to minimize the user/kernel space context switches due to socket write system calls) and a large Unix socket queue (to decouple the producer and consumer as much as possible). However, the product of the socket send buffer size and queue length must not be so large as to cause the kernel to run out of contiguous memory areas (causing write failures).
The actual figures will depend on your system configuration and usage. You will need to determine the limits by testing... start say with wmem_max
at 256Kb and max_dgram_qlen
at 32 and keep doubling wmem_max
until you notice things start breaking. You will need to adjust max_dgram_qlen
to balance the activity of the producer and consumer to a certain extent (although if the producer is much faster or much slower than the consumer, the queue size won't have much affect).
Note your producer will have to specifically setup the socket send buffer size to wmem_max
bytes with a call to setsockopt (SO_SNDBUF)
and will have to split data into wmem_max
byte chunks (and the consumer will have to reassemble them).
Best guess: the practical limits will be around wmem_max ~8Mb and unix_dgram_qlen ~32.
Maximum limit on size of data in IPC using sockets in unix
Q1) Is there a limit on the maximum limit on the size of data that I can send over the AF_UNIX,SOCK_STREAM socket ( from what I have read , I don't think there is )
You are correct. There is no real limit for SOCK_STREAM.
Q2 a) Does the socket break up the data into smaller blocks when transferring
You are correct. The stream is broken up into a manageable sized packets, negotiated by both the transmitter and the receiver.
Q2 b) and if thats the case do I need to receive the smaller blocks individually or as single block like I am doing right now.
You needn't do anything. The stream is reassembled on the other end, just as it was transmitted.
Q3) Will it be better to use AF_UNIX,SOCK_DGRAM socket here.
No. Unless you need to learn all about packet-size negotiation, checking for missing packets and having them resent, making sure that packets received out-of-order are managed properly, etc.
What is the max size of AF_UNIX datagram message in Linux?
AF_UNIX SOCK_DATAGRAM/SOCK_SEQPACKET datagrams need contiguous memory. Contiguous physical memory is hard to find, and the allocation fails, logging something similar to this on the kernel log:
udgc: page allocation failure. order:7, mode:0x44d0
[...snip...]
DMA: 185*4kB 69*8kB 34*16kB 27*32kB 11*64kB 1*128kB 1*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3788kB
Normal: 13*4kB 6*8kB 100*16kB 62*32kB 24*64kB 10*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 7012kB
[...snip...]
unix_dgram_sendmsg()
calls sock_alloc_send_skb()
lxr1, which calls sock_alloc_send_pskb()
with data_len
= 0 and header_len
= size of datagram lxr2. sock_alloc_send_pskb()
allocates header_len
from "normal" skbuff buffer space, and data_len
from scatter/gather pages lxr3. So, it looks like AF_UNIX sockets don't support scatter/gather on current Linux.
Is there a guideline for the maximum buffer size I send over a socket?
It depends on the kind of sockets. With TCP a connection is a byte stream and the OS will take care of how best to split the bytes into packets and concatenate these together at the other side.
With UDP instead each send
will result in a single UDP message (datagram) and there is an upper limit of 64k for the size of a datagram. But even while UDP supports 64k datagrams in theory it is not a good idea to use that large messages. Since the maximum transfer unit of the underlying layer is much smaller (like around 1500 bytes for Ethernet) the message needs to be fragmented and it is easy to loose a single fragment - in which case the whole message is considered lost.
Reading the maximum size of an expected packet from a C socket
As mentioned in some other comments, reading from a socket can return any number of bytes, up to the maximum requested.
A better loop, although still not without problems, would be something along these lines:
/* 4 byte message header that contains the length */
#define MSG_HEADER_SIZE 4
#define MAX_MESSAGE_LENGTH 128
struct message {
uint32_t length;
char body[MAX_MESSAGE_LENGTH];
};
#define BUFFER_SIZE 1024
char buffer[BUFFER_SIZE];
uint32_t buf_used = 0;
/* main loop */
while (1) {
n = recv(socket, buffer + buf_used, sizeof(buffer) - buf_used, 0);
if (n == -1) {
/* handle error */
exit(1);
}
if (n == 0) {
/* connection closed, do something. */
exit(1);
}
buf_used += n;
/* check for partial/completed message(s) */
while (buf_used >= MSG_HEADER_SIZE) {
struct message *cur_msg = (struct message *) buffer;
uint32_t total_msg_length;
total_msg_length = cur_msg->length + MSG_HEADER_SIZE;
/* is this message completed yet? */
if (buf_used >= total_msg_length) {
process_message(cur_msg);
/* remove message since it has been processed */
buf_used -= total_msg_length;
/* this could potentially be optimized */
memmove(buffer, buffer + total_msg_length, buf_used);
} else {
/* have incomplete message */
break;
}
}
}
For an introduction to socket programming, I would recommend checking out Beej's Guide to Network Programming.
When will a TCP network packet be fragmented at the application layer?
It will be split when it hits a network device with a lower MTU than the packet's size. Most ethernet devices are 1500, but it can often be smaller, like 1492 if that ethernet is going over PPPoE (DSL) because of the extra routing information, even lower if a second layer is added like Windows Internet Connection Sharing. And dialup is normally 576!
In general though you should remember that TCP is not a packet protocol. It uses packets at the lowest level to transmit over IP, but as far as the interface for any TCP stack is concerned, it is a stream protocol and has no requirement to provide you with a 1:1 relationship to the physical packets sent or received (for example most stacks will hold messages until a certain period of time has expired, or there are enough messages to maximize the size of the IP packet for the given MTU)
As an example if you sent two "packets" (call your send function twice), the receiving program might only receive 1 "packet" (the receiving TCP stack might combine them together). If you are implimenting a message type protocol over TCP, you should include a header at the beginning of each message (or some other header/footer mechansim) so that the receiving side can split the TCP stream back into individual messages, either when a message is received in two parts, or when several messages are received as a chunk.
Related Topics
Which Jdk's Distributions Can Run 'Javac -Source 1.6 -Target 1.5'
Pytorch Says That Cuda Is Not Available
How to Pass a Value to a Builtin Linux Kernel Module at Boot Time
Linux Synchronization with Fifo Waiting Queue
Openssl Encoding Errors While Converting Cer to Pem
Inotify - How to Find Out Which User Has Modified File
Npm Can't Install Appjs. Error: Cannot Find Module 'Graceful-Fs'
Nasm - Symbol 'Printf' Causes Overflow in R_X86_64_Pc32 Relocation
How to Change the Font Size of a Gtk.Label in Vala
Jenkins Path to Git Windows Master/Linux Slave
Branch-Specific Configuration File Maintenance with Git
Linux Command to Delete All Files Except .Git Folder
How Is Stack Size of Linux Process Related to Pthread, Fork and Exec
Telnet to Login with Username and Password to Mail Server
Check That There Are at Least Two Arguments Given in a Bash Script
.Bashrc Not Read When Shell Script Is Invoked from Desktop Shortcut