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
Welcome to
LinuxQuestions.org , a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free.
Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please
contact us . If you need to reset your password,
click here .
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a
virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month.
Click here for more info.
10-13-2013, 07:43 PM
#1
Member
Registered: Oct 2011
Posts: 75
Rep:
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;
}
10-14-2013, 03:19 AM
#2
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,864
use gdb(1) and/or strace(1) to debug your program. Also don't ignore the return value of fcntl(2)
10-14-2013, 09:00 AM
#3
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
Quote:
Originally Posted by
fantasy1215
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));
...
All times are GMT -5. The time now is 10:01 PM .
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know .
Latest Threads
LQ News