LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 01-21-2012, 01:46 AM   #1
shreekanth
LQ Newbie
 
Registered: Jan 2012
Posts: 3

Rep: Reputation: Disabled
connect system call behaviour


Hi all,

I am a writing TCP client-server program. In server, i have called listen function as below
listen(sock_fd, 1);
I ran server and client. Things went fine. Then i just tried running server and two clients (both are being run from same executable). Here i observed that, in second client, connect system call doesn't fail (i am expecting it to fail since i have given backlog as 1 in server code. you can see listen function above).

Can anybody explain why connect system call doesn't fail in this case

Thanks in advance
Shreekanth
 
Old 01-21-2012, 08:11 PM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by shreekanth View Post
Here i observed that, in second client, connect system call doesn't fail (i am expecting it to fail since i have given backlog as 1 in server code. you can see listen function above).
Are you using syncookies? If they are enabled (/proc/sys/net/ipv4/tcp_syncookies is nonzero), then the backlog is ignored; the server never responds that the connection queue is full. Instead, it uses information encoded in the TCP header the client will respond with to regenerate the connection queue entry later. The client does not notice or even know about this at all; this is purely a server-side feature. The exact mechanism is described in the linked Wikipedia article.

However, are you sure you should get a failure with the second connect(), when not using TCP syncookies? I'd expect it to occur on the third, not on the second. When the third connect() attempt occurs, you'd have one established connection, one in the pending connection queue (making it full, since you specified a backlog of 1). The third connect() would be the first one to fail. I haven't tested this, so I could be wrong; this is just my understanding. Feel free to test and report your results!
 
Old 01-22-2012, 11:17 AM   #3
shreekanth
LQ Newbie
 
Registered: Jan 2012
Posts: 3

Original Poster
Rep: Reputation: Disabled
Hi Nominal,

Thanks for your reply.

As you said, if backlog is 1, it indicates that pending connection queue length is 1. So i can have one successful connection and one pending connection. But for next instance of client, connect has to fail. But i am seeing that it doesn't.

Also i checked the /proc/sys/net/ipv4/tcp_syncookies file and it was having a non-zero value (it was actually having value as 1). I changed it to 0 using sysctl command. Then i ran server and 3 client instances. Now also I am seeing that connect call doesn't fail for client of third instance.

Here is my server and client code.

SERVER:

#include "stdio.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "string.h"
#include "signal.h"

#define SERVER_PORT 5000

int sock_fd;
int new_sockfd;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;

void *sendThread(void *arg);
void *recvThread(void *arg);

int main()
{
int ret;

sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock_fd == -1)
{
printf("socket: sys call failure\n");
return;
}

server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(ret == -1)
{
printf("bind: sys call failure\n");
return;
}

ret = listen(sock_fd, 1);
if(ret == -1)
{
printf("listen: sys call failure\n");
return;
}

int client_addr_len;
while(1)
{
client_addr_len = sizeof(client_addr);
new_sockfd = accept(sock_fd, (struct sockaddr *)&client_addr, &client_addr_len);
if(new_sockfd == -1)
{
printf("accept: sys call failure\n");
return;
}
printf("client got connected\n");
}

close(sock_fd);
close(new_sockfd);
printf("server exiting...\n");
return 0;
}

CLIENT:

#include "stdio.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "string.h"
#include "signal.h"

#define SERVER_PORT 5000

int sock_fd;
struct sockaddr_in server_addr;

int main()
{
int ret;

sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock_fd == -1)
{
printf("socket: sys call failure\n");
return;
}


server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
ret = connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(ret == -1)
{
printf("connect: sys call failure\n");
return;
}

sleep(30);
close(sock_fd);
printf("client exiting...\n");
return 0;
}

Can you let me know why this behaviour is there.


Thanks in advance
Shreekanth
 
Old 01-25-2012, 07:17 PM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by shreekanth View Post
i checked the /proc/sys/net/ipv4/tcp_syncookies file and it was having a non-zero value (it was actually having value as 1). I changed it to 0 using sysctl command. Then i ran server and 3 client instances. Now also I am seeing that connect call doesn't fail for client of third instance.
My own tests with a current Linux kernel match your results.

I would like to point out, however, that this is a good result. The backlog is a problematic concept for a system administrator; it would have been better if it had never existed at all. An application should not care how many partially open incoming requests there might be; it is something the kernel should take care of. Furthermore, most applications just use a fixed value (instead of something the administrator could set in a configuration file), making practical server load management more difficult than it would otherwise be.

At worst, you might complain that things no longer work like they used to, but that's just silly. Having the kernel ignore the backlog, and allow a large number of pending incoming connections, is a good thing. (We can discuss why, if you're unsure.)

However, I do find what actually happens quite interesting.

It seems that the Linux kernel not only accepts "extra" incoming connections, but it also seems to buffer the initial data sent by the client to the server. Based on this, I believe the socket buffers are used as a cache. I think the kernel uses the backlog parameter to allocate larger buffers initially, so it is a good idea to set it to an user-configurable value in applications.

When the client expects the server to send data first, some of the clients seem to wait forever if TCP syncookies are disabled. (I have a suspicion why this occurs.. but in any case, such a client-server design is rare.) When TCP syncookies are enabled, everything works fine, of course. I tested with a thousand parallel clients, with the server having a backlog of 1 (and an effective backlog of about 4, based on the number of clients in the connected state at the same time).

Everything worked beautifully. I simulated a slow, single-threaded server, and most of the clients timed out on their own end (189 seconds into the connect() call) -- as they should. I find this behaviour excellent, better than I expected.

I believe the Linux kernel have been designed to ignore the backlog parameter, at least in the traditional sense. Nowadays it seems to be more like a hint, at least as long as TCP syncookie support is enabled -- and I believe you should have it enabled. Still, connection backlog should be user-configurable in applications.
 
  


Reply



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 Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to write a system call which returns current system time using call by reference mukul2kul4 Debian 2 09-25-2011 11:17 PM
Unpredictable behaviour with send/recv system call rajeshwar27singh Programming 10 08-01-2011 11:23 AM
calling a system call inside a system call suresh.j Linux - Kernel 1 08-03-2010 09:28 PM
How can i make centos 4.5's system call using vDSO(call *%gs:0x10) instead of int80 tclwp Red Hat 3 08-06-2007 12:07 AM
Strange behaviour of fork call in Linux Uzair Programming 1 02-12-2003 01:37 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 10:35 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration