Thread: non-blocking socket with a timeout

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    28

    non-blocking socket with a timeout

    Hi everyone...
    I was trying to read other threads before I submit a duplicate, but I think I have some conceptual problem about setting non-blocking sockets with timeouts.

    Basically, what I want to do is setup a socket that if the send/receive wait for 10 seconds, they will move on (do other important stuff).

    That said, I realized that I need a non-blocking socket. This is the code (in snippets) that I have so far but I am not seeing what I think I should.

    Code:
       	/* set timeouts for send/receive on this socket */
    	tv.tv_sec = 10; /* seconds */
    	tv.tv_usec = 0;
    	opt = 1;
    
    	/* Hard coded for now */
    	port_num = 5432;
    
    	/* Create our socket */
    	main_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    	/* Set it up with an address */
    	memset(&sock_info, 0, sizeof(struct sockaddr_in));
    	sock_info.sin_family = AF_INET;
    	sock_info.sin_port = htons((unsigned short)port_num);
    	sock_info.sin_addr.s_addr = htonl(INADDR_ANY);
    	status = bind(main_socket, &sock_info, sizeof(struct sockaddr_in));
    	/* listen for connection requests */
    	status = listen(main_socket, 1); /* set to only one connection */
    
    		/* Wait until we get one */
    		accept_socket = -1;
    		accept_socket = accept(main_socket, &client_info, &info_len);
    		if (accept_socket > 0)
    		{
    			ioctl(accept_socket, FIONBIO, &opt);
    
    			
    			if(setsockopt(accept_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
    			{
    				printf("Cannot Set SO_SNDTIMEO for socket\n");
    			}
    			
    			if(setsockopt(accept_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
    			{
    				printf("Cannot Set SO_RCVTIMEO for socket\n");
    			}
    		}
    After this point, I expect the socket to wait until it receives a packet for 10 seconds before it barfs...

    Code:
            rcv_len = recv(accept_socket, my_message, MSG_SIZE, 0);
    	if( rcv_len < 0)
    	{
    		printf("Nothing received");
    	}
    	else if(rcv_len >= 0)
    	{
    		printf("Received something2...");
    	}
            ...
            ...
            ...
            ...
    but it takes less than a second to quit on me...

    By the way, I know that some might recommend
    fcntl( accept_socket, O_NONBLOCK, 0 );
    over what I have, but I am required to use the method I included in the code.

    Can anyone shed some light on my senario?

    thanks in advance.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I've never heard of send/receive timeouts.

    My first google hit doesn't inspire confidence.
    SO_SNDTIMEO / SO_RCVTIMEO [Archive] - UNIX Socket FAQ
    Admittedly, it is from 2003, so perhaps some things have been fixed.

    Why not use select() with a timeout?

    And when you say "but it takes less than a second to quit on me", what do you mean?
    Where is your code to check errno for example?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2010
    Posts
    28
    Thanks Salem for your reply.
    I did leave out a bit of code that does error handling and checking.

    Before I clarify what I meant with "takes less than a second to quit on me" let me say this first.

    In a blocking socket, a recv() function call will hold until something is received, hence the blocking part of the socket. However, when I set the socket to non-blocking, my understanding is that a recv() call will wait x seconds (based on what I set the SO_RCVTIMEO value to) and then it exists with an error -1 and errno set properly. However, this is not happening.

    As I mentioned in my first (original) post, is I could easily have some conceptual misunderstanding.

    How do I use the select() function? I guess I could also read up on it but if you don't mind dropping a few lines that would be greatly appreciated.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The call is returning immediately because you've set the socket to NON-BLOCKING. Using a timeout with a non-blocking socket makes no sense. If you want timed reads/writes, just configure the timeouts and go.

    Having said that, this options are not really reliable. You should be using select() instead (and in the case of select, you really do want to make the sockets non-blocking, but for other reasons...)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    Apr 2010
    Posts
    28
    Thanks brewbuck.
    So now I have re-written some of the code to utilize the select() function among others FD_SET, FD_ISSET, etc...
    I am still seeing some weird behavior, but I will work on it some more and see if I still need to post a question about it....

    Thanks for the reply again.

  6. #6
    Registered User
    Join Date
    Apr 2010
    Posts
    28
    I need to ask a really dumb question....
    If I create a non-blocking socket, it needs to be implemented on the host and the client, correct?

    thanks

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > If I create a non-blocking socket, it needs to be implemented on the host and the client, correct?
    No, the host and client are independent entities.
    How would you know whether the webserver on this (or any other site) was using say non-blocking sockets?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Apr 2010
    Posts
    28
    Salem,
    Thanks again for your input. I guess I wasn't thinking too much about it or else the scenario you mentioned would clearly provide an answer.

    My question now is after looking at this for some time, I am starting to get the hang of it, but i wanted to know if I can do something like the following code. What I want to do is I want to use the select for send() and recv() functions to synch. I might still be using the code incorrectly, but I thought I would dump it here and get someone more knowledgeable to look at it.

    Code:
    ...
    ...
    ...
    
    FD_ZERO(&read_mask);
    FD_ZERO(&write_mask);
    
    FD_SET(accept_socket, &read_mask);
    FD_SET(accept_socket, &write_mask);
    
    /* handle receiving the packet */
    select_return = select(accept_socket, &read_mask, (fd_set *)0, (fd_set *)0, &tv);
    if(select_return < 0) /* [timeout=0, -1= ERROR] is returned */
    {
    	printf("recv: select functions returned -1 error value\n");
    }
    else if(select_return == 0)
    {
    	printf("recv: select functions returned 0 timeout value\n");
    }
    else
    {
    	printf("recv: select functions returned a positive value\n");
    	
    	if(FD_ISSET(accept_socket, &read_mask))
    	{
    		/*  HAND SHAKE AS A START */
    		rcv_len = recv(accept_socket, myDmsg, MSG_SIZE, 0);
    				
    		if( rcv_len < 0)
    		{
    			strcpy(myDmsg, "Nothing received");
    			isConnected = FALSE;
    		}
    		else if(rcv_len >= 0)
    		{
    			strcpy(myDmsg, "Received something2...");
    		}
    	}
    }
    
    /* handle sending the packet */
    select_return = select(accept_socket, (fd_set *)0, &write_mask, (fd_set *)0, &tv);
    
    if(select_return < 0) /* [timeout=0, -1= ERROR] is returned */
    {
    	printf("send: select functions returned -1 error value\n");
    }
    else if(select_return == 0)
    {
    	printf("send: select functions returned 0 timeout value\n");
    }
    else
    {
    	printf("send: select functions returned a positive value\n");
    			
    	if( send(accept_socket, myDmsg, strlen(myDmsg), 0) < 0)
    	{
    		/* an error occurred. Handle it appropriately (TODO) */
    	}
    }
    ...
    ...
    ...

  9. #9
    Registered User
    Join Date
    Apr 2010
    Posts
    28
    Adding some comments.
    The previous code seems to actually work (post #8) with the one minor change of all select functions need to be as follows:
    Code:
    select_return = select(accept_socket+1, ..... );
    That did the trick.....
    thanks everyone who provided some comments and thoughts regarding this question.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Nonblocking socket...blocking?
    By zolom in forum Networking/Device Communication
    Replies: 2
    Last Post: 07-13-2009, 12:06 PM
  2. how to intilise a non blocking socket?
    By lolguy in forum Networking/Device Communication
    Replies: 7
    Last Post: 03-20-2009, 12:18 AM
  3. Replies: 8
    Last Post: 03-10-2008, 11:57 AM
  4. How to initialize a non blocking socket using only winsock library
    By *DEAD* in forum Networking/Device Communication
    Replies: 4
    Last Post: 01-18-2008, 07:03 AM
  5. Socket Blocking Trouble!
    By LearningMan in forum Windows Programming
    Replies: 6
    Last Post: 01-09-2003, 10:09 AM

Tags for this Thread