Re: maximum timeout on socket connection
From: Sean Burke (foobar_at_mystery.org)
Date: 03/22/04
- Next message: BrandonInDenver: "Connect() problems"
- Previous message: pxlai625: "Re: Opening file for simultaneous read and write"
- In reply to: Jo: "Re: maximum timeout on socket connection"
- Next in thread: Jo: "Re: maximum timeout on socket connection"
- Reply: Jo: "Re: maximum timeout on socket connection"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 22 Mar 2004 05:46:43 GMT
JoJoTwilligo@hotmail.com (Jo) writes:
> Sean Burke <foobar@mystery.org> wrote in message news:<x7ptb9eubz.fsf@bolo.xenadyne.com>...
> > "Marc Rochkind" <rochkind@basepath.com> writes:
> >
> > > --
> > > Marc Rochkind
> > > "Advanced UNIX Programming" (publishing April 2004)
> > > www.basepath.com/aup
> > >
> > > "Jo" <JoJoTwilligo@hotmail.com> wrote in message
> > > news:72ce7f0c.0403181136.3def0332@posting.google.com...
> > > > A few weeks ago I posted a question about setting a maximum timeout on
> > > > the connect() function. I also wanted to avoid the complexity of
> > > > making the function non-blocking, and working with select(). The
> > > > conclusion was unclear, but it seemed the best method was to set an
> > > > alarm. For some reason this didn't work at all--the alarm seemed to
> > > > have no affect. Here's my code:
> > > >
> > > > int connectex(int sockfd, const struct sockaddr *serv_addr, socklen_t
> > > > addrlen, long maxTimeOut) {
> > > > sig_t oldhandler;
> > > > if (maxTimeOut != -1) {
> > > > oldhandler = signal(SIGALRM, SIG_IGN);
> > > > alarm(maxTimeOut);
> > > > }
> > > > int returned = connect(sockfd, serv_addr, addrlen);
> > > > if (maxTimeOut != -1) {
> > > > alarm(0);
> > > > signal(SIGALRM, oldhandler);
> > > > }
> > > >
> > > > return returned;
> > > > }
> > > >
> > > > I was told to set SIGALRM to SIG_IGN. Presumably, this would not
> > > > prevent the alarm from affecting connect(). In fact, the tests I did
> > > > with and without the signal() call were just the same.
> > > > I do have a signal handler, but it is only handles SIGSEGV.
>
> [snip]
>
> >
> > I would suggest that you question your assumption that
> > using signals is the easist way to do it. You may find
> > that using select() is not nearly as complicated as you
> > expect.
>
> I'm not quite sure what question to ask. Can you tell me how I
> might use the select in a simple way, such that it would set a maximum
> timeout on the connect()? I'd prefer it not interfere with the other
> operations on the socket.
Something similar to this should do it.
Note that I haven't actually compiled it.
-SEan
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
/*
* Connect a socket.
*
* returns zero on success, ETIME on timeout, errno on connect failure.
*/
int connectex(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, long maxTimeOut)
{
/* Make socket nonblocking.
*/
socket_set_nonblocking(sockfd, true);
/* Connect the socket.
*/
if (connect(sockfd, serv_addr, addr_len)) < 0)
{
if (errno == EINPROGRESS)
{
fd_set fds;
int numfds = 0;
struct timeval timeout;
int r, error;
/* Clear the fd_set.
*/
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
numfds = sockfd + 1;
timeout.tv_sec = maxTimeOut;
timeout.tv_usec= 0;
switch (r = select(numfds, NULL, &fds, NULL, &timeout))
{
case -1:
perror("select failed");
return errno;
case 0:
/* select timed out.
*/
close(sockfd);
return ETIME;
case 1:
if ((error = socket_get_error(sockfd)) == 0)
{
/* Connect succeeded asynchronously.
*/
socket_set_nonblocking(sockfd, false);
return 0;
}
else
{
fprintf(stderr, "connect(%d) failed with error %d - %s",
sockfd, error, strerror(error));
return error;
}
}
}
else
{
fprintf(stderr, "connect(%d) failed with error %d - %s",
sockfd, errno, strerror(errno));
return errno;
}
}
else
{
/* Connect succeeded immediately.
*/
return 0;
}
}
static int
socket_set_nonblocking(int sock, bool mode)
{
int flags = fcntl(sock, F_GETFL, 0);
if (flags == -1)
return errno;
else if ( mode && !(flags & O_NONBLOCK))
flags |= O_NONBLOCK;
else if (!mode && (flags & O_NONBLOCK))
flags ^= O_NONBLOCK;
else
return OK; /* blocking mode is already good. */
if (fcntl(sock, F_SETFL, flags) < 0)
{
fprintf(stderr, "fcntl failed: errno %d - %s", errno, safe_strerror(errno));
return errno;
}
return 0;
}
static int
socket_get_error(int sock)
{
int error;
int len = sizeof(error);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) == 0)
{
return error;
}
else
{
fprintf(stderr, "getsockopt(%d) failed with errno %d - %s", sock, errno, strerror(errno));
return errno;
}
}
- Next message: BrandonInDenver: "Connect() problems"
- Previous message: pxlai625: "Re: Opening file for simultaneous read and write"
- In reply to: Jo: "Re: maximum timeout on socket connection"
- Next in thread: Jo: "Re: maximum timeout on socket connection"
- Reply: Jo: "Re: maximum timeout on socket connection"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|