LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-13-2013, 07:43 PM   #1
fantasy1215
Member
 
Registered: Oct 2011
Posts: 75

Rep: Reputation: Disabled
linux socket connect timeout implementation problem.


I implement my linux client side socket class. I want my client side connect with timeout. Based upon the code following the link. (http://www.cs.cmu.edu/afs/cs/academi...connect_nonb.c) But it seemed that the client connection still didn't timeout.

I write a test server and client code. I make the server code to sleep 120s before accept the client connection, and I want my client connection timeout 5s. But my code seemed the client still wait 120s to connect to the server while not timeout. If someone guru would be nice to point out my mistakes. Thanks in advance!

The client class I implemented.
Code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <stdexcept>
#include <fcntl.h>

#define INVALID_HANDLE -1

class CMSocket
{
public:
	CMSocket()
	{
		_sockfd = -1;
	}
	~CMSocket()
	{
		Close();
	}
	void Close()
	{
		if (-1 != _sockfd)
		{
			cout<< "socket_class close FD:" << _sockfd <<endl;
			close(_sockfd);
			_sockfd = -1;
		}
	}
	int GetHandle()
	{
		return _sockfd;
	}
	bool Connect(const char* servIPorHost, const char* port, int timeout)
	{
		if (NULL == servIPorHost || NULL == port || *servIPorHost == '\0' || *port == '\0')
		{
			return false;
		}
		string lshost(servIPorHost);
		string lsport(port);
		return Connect(lshost, lsport, timeout);
	}
	bool Connect(const std::string& servIP, const std::string& port, int timeout)
	{
		struct sockaddr_in sa;
		int                err;
		memset (&sa, '\0', sizeof(sa));
		sa.sin_family      = AF_INET;
		sa.sin_addr.s_addr = inet_addr (servIP.c_str());   /* Server IP */
		sa.sin_port        = htons     ( atoi(port.c_str()) );          /* Server Port number */
		_sockfd = socket (AF_INET, SOCK_STREAM, 0);
		if(_sockfd < 0)
		{
			m_lasterror = errno; m_ss.str("");
			m_ss<< __FILE__ <<"," <<__LINE__ <<" socket return < 0, error[" << strerror(m_lasterror) <<"]";
			return false;
		}
		cout<<"socket return mysock[" << _sockfd <<"]" <<endl;
		
		
		SetNonBlocking();
		
		err = connect(_sockfd, (struct sockaddr*) &sa, sizeof(sa));
		m_lasterror = errno;
		cout<<"xxxxxxxxxxxx connect return val[" << err <<"], [" << strerror(errno)  <<"], timeout val[" << timeout<<"]" <<endl;
	
		if( err < 0)
		{
			if(m_lasterror != EINPROGRESS)
			{
				m_ss.str("");
				m_ss<< __FILE__ <<"," <<__LINE__ <<" connect error[" << strerror(m_lasterror) <<"]";
				return false;
			}
			else
			{
				int sret(-1), error(-1);
				socklen_t len(0);
				fd_set rset, wset, *rpset(NULL), *wpset(NULL);
				struct timeval tv, *tp(NULL);
				do
				{
					//select
					//FD_ZERO(&rset); FD_SET(_sockfd, &rset); rpset = &rset;
					FD_ZERO(&wset); FD_SET(_sockfd, &wset); wpset = &wset;
					tv.tv_sec  = timeout;
					//tv.tv_usec = (int)((timeout-tv.tv_sec)*1.0e6);
					tv.tv_usec = 0;
					tp = &tv;
					sret = select(_sockfd+1, NULL, wpset, NULL, tp);
					cout<<"select return[" << sret <<"], errno[" << errno <<"], msg[" << strerror(errno) <<"]" <<endl;
					m_lasterror = errno;
				} while( sret == -1 && errno == EINTR);
				if(sret < 0) //select error
				{
					m_ss.str("");
					m_ss<< __FILE__ <<"," <<__LINE__ <<" connect select error[" << strerror(m_lasterror) <<"]";
					return false;
				}
				else if(sret == 0) //select timeout
				{
					//m_lasterror = ETIMEOUT;
					m_ss.str("");
					m_ss<< __FILE__ <<"," <<__LINE__ <<" connect select timeout[" << strerror(m_lasterror) <<"]";
					return false;
				}
				else
				{
					if(FD_ISSET(_sockfd, &wset))
					{
						cout<<"write set is true" <<endl;
					}
					else
					{
						cout<<"write set is false" <<endl;
					}
					//if(FD_ISSET(_sockfd, &rset) || FD_ISSET(_sockfd, &wset))
					if( FD_ISSET(_sockfd, &wset))
					{
						len = sizeof(error);
						if(getsockopt(_sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
						{
							m_lasterror = errno; m_ss.str("");
							m_ss<< __FILE__ <<"," <<__LINE__ <<" getsockopt return error[" << strerror(m_lasterror) <<"]" <<endl;
							return false;
						}
						if(error)
						{
							m_ss.str("");
							m_ss<< __FILE__ <<"," <<__LINE__ <<" getsockopt socket is error[" << strerror(error) <<"], [" << error <<"]" <<endl;
							return false;
						}
					}
					else
					{
						m_ss.str("");
						m_ss<< __FILE__ <<"," <<__LINE__ <<" FD_ISSET none is set" <<endl;
						return false;
					}
				}
			}
		}
		
		
		
		
		
		SetBlocking();
		
		
		
		
		return true;
	}
	int Send(const string& msg, time_t timedout)
	{
		return write(_sockfd, msg.c_str(), msg.length());
	}
	int Receive(string& rcvmsg, int lentorcv, time_t timeout)
	{
		rcvmsg.clear();
		fd_set rdset;
		int result;
		struct timeval tmout;
		tmout.tv_sec = timeout-time(0);
		tmout.tv_usec = 0;
		// int lsec = timeout-time(0);
		// cout<< "set timeout sec is:" <<lsec <<", sockfd is:" <<_sockfd <<endl;
		
		do{
			FD_ZERO(&rdset);
			FD_SET( _sockfd, &rdset );
			result = select( _sockfd+1, &rdset, NULL, NULL, &tmout );
		}while( result == -1 && errno == EINTR );
		
		cout<< "select_result_is:"<<result <<endl;
		
		if( result < 0 )
		{
			throw runtime_error( "select_error_happen_throw_execption" );
		}
		if(result == 0)
		{
			throw runtime_error( "select_maybe_timeout_too");
		}
		if( result>0 && !FD_ISSET(_sockfd, &rdset) )
		{
			cout<<"sockfd_is_not_set" <<endl;
			throw runtime_error( "Receive_timeout_happen, no data ready to read" );
		}
		
		const int buflen = 1024;
		char rcvbuf[buflen+1] = {0};
		int ileft = lentorcv;
		int iread = 0;
		while (ileft > 0)
		{
			memset(rcvbuf, 0x00, sizeof(rcvbuf));
			if ((iread = read(_sockfd, rcvbuf, ileft>buflen ? buflen: ileft ))>0)
			{
				rcvmsg.append(rcvbuf);
				ileft -= iread;
			}
			else
			{
				break;
			}
		}
		
		return 0;
	}
	void SetBlocking()
	{
		if( _sockfd == INVALID_HANDLE ) return;
		int flags = fcntl(_sockfd, F_GETFL, 0);
		flags &= (~(O_NONBLOCK));
		fcntl(_sockfd, F_SETFL, flags);
	}
	
	void SetNonBlocking()
	{
		if( _sockfd == INVALID_HANDLE ) return;
		int flags = fcntl(_sockfd, F_GETFL, 0);
		flags |= O_NONBLOCK;
		fcntl(_sockfd, F_SETFL, flags);
	}


protected:
private:
	int          _sockfd;
	int          m_lasterror;
	string       _servinfo;
	stringstream m_ss;
};

char* servip = NULL;
char* servport = 0;
#define MTIMEOUT  5
#define THREADS   1

void *threadfunc(void *parm)
{
	CMSocket clientsock;
	if( !clientsock.Connect( servip, servport, 5 ) )
	{
		cout<<"exit thread,connect to serv err:" << servip <<"," << servport <<endl;
		return NULL;
	}
	cout<<"connection ok, to{" << servip <<":" << servport <<"}" <<endl;
	pthread_exit((void*)NULL);
}

void createConnThread()
{
	int loop;
	pthread_t threadid [ THREADS ];
	pthread_attr_t        pta;
	pthread_attr_init(&pta);
	pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_JOINABLE);
	for (loop=0; loop<THREADS; ++loop)
	{
		pthread_create(&threadid[loop], &pta, threadfunc, NULL);
	}
	for (loop=0; loop<THREADS; ++loop) 
	{
		pthread_join(threadid[loop], NULL);
	}
	pthread_attr_destroy(&pta);
}

int main(int argc, char* argv[] )
{
	if( argc == 3 )
	{
		servip = argv[1];
		servport = argv[2];
	}
	else
	{
		servip = "175.10.1.144";
		servport = "17777";
	}
	createConnThread();
	return 0;
}


The test server side code. The server side code did nothing just accept the client connection(before accept sleep a long time to make the client connection timeout) then close it.
Code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <stdexcept>
#include <fcntl.h>

int passivesock(const char* servip, const char* servport, int qlen)
{
	cout<<"want to conn to server{" << servip<<":" <<servport <<"}" <<endl;
	sockaddr_in sin;
	int s;
	memset(&sin, 0x00, sizeof(sin));
	sin.sin_family = AF_INET;
	if( NULL == servip )
	{
		sin.sin_addr.s_addr = INADDR_ANY;
	}
	else
	{
		int ires;
		ires = inet_pton(AF_INET, servip, &(sin.sin_addr));
		if( ires <= 0 )
		{
			cout<< "not_a valid ip:{" << servip <<"}" << endl;
			return -1;
		}
	}

	sin.sin_port = htons( atoi( servport ) );

	s = socket(PF_INET, SOCK_STREAM, 0);
	if(s < 0)
	{
		cout<<"socket err" <<endl;
		exit(-1);
	}
	cout<<"sock fd is:" <<s <<endl;
	int reuseflag = 1;
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseflag, sizeof(reuseflag));
	int temperr = 0;
	if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		temperr = errno;
		close(s);
		cout<<"bind err:" <<strerror(temperr) <<endl;
		exit(-1);
	}
	if( listen(s, qlen) < 0)
	{
		int temperr = errno;
		close(s);
		cout<<"can't listen, err:" <<strerror( temperr ) <<endl;
		exit(-1);
	}
	return s;
}

int main(int argc, char* argv[])
{
	sockaddr_in fsin;
	int msock, ssock;
	socklen_t alen;
	msock = passivesock( "175.10.1.144", "17777", 10 );
	while(1)
	{
		alen = sizeof( fsin );
		//before accept sleep  seconds make the client connect timeout
		sleep(120);
		ssock = accept(msock, (struct sockaddr*)&fsin, &alen);
		close( ssock );
	}
	close(msock);
	return 0;
}
 
Old 10-14-2013, 03:19 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,864
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
use gdb(1) and/or strace(1) to debug your program. Also don't ignore the return value of fcntl(2)
 
Old 10-14-2013, 09:00 AM   #3
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by fantasy1215 View Post
I write a test server and client code. I make the server code to sleep 120s before accept the client connection, and I want my client connection timeout 5s. But my code seemed the client still wait 120s to connect to the server while not timeout. If someone guru would be nice to point out my mistakes. Thanks in advance!
If you want the connect() to timeout in 5 seconds (or any other designated time period), you can set up the socket's "send timeout" attribute. For example (see code in bold text):
Code:
...
		_sockfd = socket (AF_INET, SOCK_STREAM, 0);
		if(_sockfd < 0)
		{
			m_lasterror = errno; m_ss.str("");
			m_ss<< __FILE__ <<"," <<__LINE__ <<" socket return < 0, error[" << strerror(m_lasterror) <<"]";
			return false;
		}
		cout<<"socket return mysock[" << _sockfd <<"]" <<endl;
		
		
		SetNonBlocking();


                struct timeval timeout = { 5, 0 };   // 5 seconds, 0 microseconds

                if (setsockopt(_sockfd, SOL_SOCKET, SO_SNDTIMEO, (const void*) &timeout, sizeof(timeout)) != 0)
		{
			m_lasterror = errno; m_ss.str("");
			m_ss<< __FILE__ <<"," <<__LINE__ <<" socket return < 0, error[" << strerror(m_lasterror) <<"]";
			return false;
		}
		
		err = connect(_sockfd, (struct sockaddr*) &sa, sizeof(sa));
...
 
  


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
centos v5.2: occasional socket select() problem when zero timeout is specified mobrientx Linux - Networking 1 10-31-2009 01:26 PM
socket - select() timeout problem in Linux Tejesh Linux - Networking 2 06-10-2009 04:38 AM
help!!! how can i timeout a socket connect call... ? bzImage Programming 1 03-06-2002 02:54 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:01 PM.

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