LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 06-12-2014, 10:43 PM   #1
roland.ames
LQ Newbie
 
Registered: Jun 2014
Location: Perth, Western Australia
Posts: 2

Rep: Reputation: Disabled
how do I detect a TCP connection disconnected from the other end


I have a thread in my process that acts as a simpe TCP server it should:
1) listen for an incoming tcp conection request,
2) then accept that connetion,
3) then wait for the disconnect from the other end.

The problem is in step 3) detecting the remote disconnection. I am using poll to wait for either of two events; another connection attempt or a disconnection.

Code:
#define LISTEN_EVENTS	(POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)

#ifdef __USE_GNU
#define TCP_EVENTS		(POLLRDHUP | POLLERR | POLLHUP | POLLNVAL)
#else
#define TCP_EVENTS		(POLLERR | POLLHUP | POLLNVAL)
#endif

Code:
...

                	struct pollfd ufds[2];
                	ufds[0].fd = fd_Listen;
                	ufds[0].events = LISTEN_EVENTS;
                	ufds[1].fd = fd_TcpStdio;
                	ufds[1].events = TCP_EVENTS;

                	int poll_count = poll(ufds,2,-1);
                	if ( poll_count >= 0 )
                    {

                        fprintf(stderr, "poll returned n = %i, listen events = %04X, TCP events = %04X\n", poll_count, ufds[0].revents, ufds[1].revents);

...

My problem is that the poll() will return if another connection atempt is made, but will not return when the connection is dropped from the other end.

I could use keep-alive, but I want to know if it is possible to detect just the fact that the connection is closed remotely, without having to attempt to read or write to the TCP stream?
 
Old 06-13-2014, 05:35 PM   #2
Pearlseattle
Member
 
Registered: Aug 2007
Location: Zurich, Switzerland
Distribution: Gentoo
Posts: 934

Rep: Reputation: 104Reputation: 104
Hi
Quote:
I could use keep-alive, but I want to know if it is possible to detect just the fact that the connection is closed remotely, without having to attempt to read or write to the TCP stream?
I would think that if the remote host closes the connection, it will just free up the resources (threads, memory, anything...) linked to the handle which is responsible for that particular connection and that it won't do anything fancy like sending you a specific message that signals to you that the connection is about to be or was closed (well, it probably depends on what kind of service is connecting to you - depending on how it is programmed).
 
Old 06-13-2014, 06:24 PM   #3
stateless
Member
 
Registered: Jan 2013
Distribution: Debian
Posts: 166
Blog Entries: 1

Rep: Reputation: 4
Quote:
Originally Posted by Pearlseattle View Post
Hi

I would think that if the remote host closes the connection, it will just free up the resources (threads, memory, anything...) linked to the handle which is responsible for that particular connection and that it won't do anything fancy like sending you a specific message that signals to you that the connection is about to be or was closed (well, it probably depends on what kind of service is connecting to you - depending on how it is programmed).
The remote host is supposed to send you TCP CLOSE. http://www.tcpipguide.com/free/t_TCP...mination-2.htm

But it is always possible that they won't be able to for some reason, and the connection dies improperly. E.g., somebody hits the power switch, cable gets unplugged, OS kernel panic... So I think you have to keep alive if you want to be absolutely sure the connection hasn't died.
 
2 members found this post helpful.
Old 06-14-2014, 08:46 AM   #4
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,604

Rep: Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241Reputation: 1241
The usual way is to detect and EOF from the file descriptor used for I/O. You can also detect the close from a write that terminates early (return status... and test for EOF).
 
3 members found this post helpful.
Old 06-14-2014, 09:58 PM   #5
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.8, Centos 5.10
Posts: 17,240

Rep: Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324Reputation: 2324
You should read this; a very good guide http://beej.us/guide/bgnet/
 
Old 06-20-2014, 05:14 AM   #6
roland.ames
LQ Newbie
 
Registered: Jun 2014
Location: Perth, Western Australia
Posts: 2

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by jpollard View Post
The usual way is to detect and EOF from the file descriptor used for I/O. You can also detect the close from a write that terminates early (return status... and test for EOF).
thanks, this was the information I needed, I was originally using select() with the TCP file descriptor addded to the exceptfds, but this did not work, so I tried poll().

But now I have found that when the TCP connection is closed from the remote end, it does flag 'read available', but the attempt to read returns 0 data bytes.
So now I am doing this:

Code:
...
                    fd_set read_fds;
                    fd_set error_fds;
                    FD_ZERO( &read_fds );
                    FD_ZERO( &error_fds );
                    FD_SET( fd_Listen, &read_fds );
                    FD_SET( fd_TcpStdio, &read_fds );
                    FD_SET( fd_TcpStdio, &error_fds );

                	int select_count = select( FD_SETSIZE, &read_fds, NULL, &error_fds, NULL );
                    if (select_count)
                    {
//                        fprintf(stderr, "select returned n = %i", select_count );
//                        if ( FD_ISSET(fd_Listen,&read_fds) )	fprintf(stderr,", fd_Listen is in read_fds");
//                        if ( FD_ISSET(fd_TcpStdio,&read_fds) )	fprintf(stderr,", fd_TcpStdio is read_fds");
//                        if ( FD_ISSET(fd_TcpStdio,&error_fds) )	fprintf(stderr,", fd_TcpStdio is in error_fds");
//                        fputc('\n', stderr);

                    	if ( FD_ISSET(fd_Listen,&read_fds) )
                    	{
                    		puts_to_stderr("another TCP connection request received, so we close this one and allow the new connection to be accepted");
                    		restore = TRUE;
                    	}
                    	else if ( FD_ISSET(fd_TcpStdio,&read_fds) )
                    	{
                    		int n;
                    		puts_to_stderr("read available on fd_TcpStdio");

//                    		char b;
//                    		n = recv(fd_TcpStdio,&b,1,MSG_PEEK);
//                    		fprintf(stderr,"recv returns n = %i\n", n);
//                    		if ( n!=1 )
//                    		{
//                    			restore = TRUE;
//                    		}

                    		if ( ioctl(fd_TcpStdio,FIONREAD,&n) < 0 )
                    		{
                    			perror("ioctl error");
                    		}
                    		else
                    		{
                    			fprintf(stderr,"ioctl returns n = %i\n", n);
                    			if ( n==0 )
                    			{
                    				restore = TRUE;
                    			}
                    		}

                    	}
                    	else if ( FD_ISSET(fd_TcpStdio,&error_fds) )
                    	{
                    		puts_to_stderr("error on fd_TcpStdio");
                    		restore = TRUE;
                    	}
...
setting the restore flag is what I do when I am ready to close fd_TcpStdio and listen / accept a new connection.
notice this code will not read from the fd_TcpStdio stream, if there is actual data coming in on this stream it is handled by a different thread, and this should not be considered a disconnection trigger.
The commented out recv with MSG_PEEK works just as well, but ioctl with FIONREAD seems more elegant (no need for 'char b', if there is real incoming data I don't need to see it).
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] How to detect a closed tcp client connection when client is only receiving data programlight Programming 9 10-24-2011 10:19 AM
Is there a solution for the WIFI connection getting disconnected? SHARK13 Linux - Newbie 1 05-16-2011 09:55 PM
Lose Wireless Connection when Wired connection is disconnected phillywill Linux - Wireless Networking 65 01-21-2010 09:40 PM
Sysctl : How to detect TCP connection lost faster? philipina Linux - Networking 1 11-08-2008 02:20 PM


All times are GMT -5. The time now is 09:01 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration