I have a client and a server implemented using Unix domain socket.
I want to see how much data the client can push on to the socket without the server reading off that data. I was expecting the client to be able to send around 20-30KB data before it got blocked. I have checked the net.core.rmem_default, net.core.wmem_default, net.core.rmem_max, net.core.wmem_max, and net.unix.max_dgram_qlen sysctl options and am sure i am not hitting these values. I also increased net.unix.max_dgram_qlen values but doesnt seem to help.
I was quite surprised to see that the number of fixed sized messages that i was able to send was around 138. This number remained constant even after i reduce the size of my messages.
On the client side i go into a loop and write 1024 messages.
CLIENT CODE
void write_text (int socket_fd, char* text)
{
int length = strlen (text) + 1;
send (socket_fd, &length, sizeof (length),0);
/* Write the string. */
send (socket_fd, text, length,0);
}
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1];
char message[100];
int socket_fd;
int loop = 0;
struct sockaddr_un name;
/* Create the socket. */
socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
/* Store the server's name in the socket address. */
name.sun_family = AF_UNIX;
strcpy (name.sun_path, socket_name);
/* Connect the socket. */
connect (socket_fd, (struct sockaddr *) &name, SUN_LEN (&name));
for (loop=0;loop<1024;loop++)
{
sprintf (message, "message number %d coming from the client", loop);
/* Write the text on the command line to the socket. */
write_text (socket_fd, message);
}
close (socket_fd);
return 0;
}
SERVER SIDE CODE:
unsigned int global_flag = 0;
int client_socket_fd = 0;
int server (int client_socket)
{
while (1)
{
int length;
char* text;
if (read (client_socket, &length, sizeof (length)) == 0)
return 0;
text = (char*) malloc (length);
read (client_socket, text, length);
printf ("length %d %s\n", length, text);
if (global_flag<5) break;
free (text);
}
return 0;
}
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1];
int socket_fd;
struct sockaddr_un name;
int client_sent_quit_message;
socklen_t socket_length = sizeof(struct sockaddr_un);
int result;
int len = sizeof (int);
int data = 0;
socket_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
name.sun_family = AF_UNIX;
strcpy (name.sun_path, socket_name);
socket_length = strlen(name.sun_path) + sizeof (name.sun_family);
bind (socket_fd, (struct sockaddr *) &name, socket_length);
listen (socket_fd, 5);
while (1)
{
struct sockaddr_un client_name;
socklen_t client_name_len;
/* Accept a connection. */
client_socket_fd = accept (socket_fd, (struct sockaddr *) &client_name, &client_name_len);
client_sent_quit_message = server (client_socket_fd);
}
/* Remove the socket file. */
close (socket_fd);
unlink (socket_name);
return 0;
}
In the server side code global_flag is always less than 0 and the server hence does one read and comes out. There are no more reads done by the server. The client meanwhile is pushing data on the socket.
I did a strace on the client and got this:
VirtualBox:~/code/linux$ strace ./unix-client /tmp/unixtest
execve("./unix-client", ["./unix-client", "/tmp/unixtest"], [/* 44 vars */]) = 0
brk(0) = 0x1245000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3e12b63000
fstat(3, {st_mode=S_IFREG|0644, st_size=68001, ...}) = 0
mmap(NULL, 68001, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3e12b52000
close(3) = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, ...}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f3e12583000
[clipped]
socket(PF_FILE, SOCK_STREAM, 0) = 3
connect(3, {sa_family=AF_FILE, path="/tmp/unixtest"}, 15) = 0
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 0 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 1 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 2 coming from the"..., 40, 0, NULL, 0) = 40
sendto(3, "(\0\0\0", 4, 0, NULL, 0) = 4
..
sendto(3, "message number 138 coming from t"..., 42, 0, NULL, 0) = 42
sendto(3, "*\0\0\0", 4, 0, NULL, 0) = 4
sendto(3, "message number 139 coming from t"..., 42, 0, NULL, 0) = 42
sendto(3, "*\0\0\0", 4, 0, NULL, 0
[AND THE CLIENT BLOCKS HERE]
Any idea why the client gets blocked after sending 139 messages when the server has stopped draining messages from the socket?
I would presume that the number of messages that the client can send on the socket would increase if i reduce the size of the message. However, i see that it remains constant. Irrespective of the size of the message the client is not able to send more than 139 messages on the socket without getting blocked.