• C

Connection hangs using C Socket Library

I'm using the C socket library to create a program which downloads and processes certain html documents.

Sometimes, however, I come accross a site that works fine on a browser or with wget, but will cause my program to hang endlessly when I try to download it using the C socket library.  

The routine where the data is actually downloaded is this:

      char buf[MAXRECV + 1];
      int status;
      while (status != 0) {
            memset(buf, 0, MAXRECV + 1);
            status = ::recv(m_sock, buf, MAXRECV, 0); // this statement causes the hang
      }

An example website which works normally through a browser, but hangs with C socket library is http://natzoo.si.edu/Animals/WebCams/

Can anyone offer some possible explanations for this?

Thanks.
chsalviaAsked:
Who is Participating?
 
ikeworkCommented:
seems you run sockets in synchronous mode, so recv is waiting for incoming data, if you want it to exit, if nothing is available, you have to run sockets in asynchronous mode (nonblocking sockets).

here is an example, how to set a socket nonblocking (non-win-example) :

http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWdev/NETPROTO/p37.html


ike
0
 
ikeworkCommented:
here is another one:

http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzab6/rzab6xnonblock.htm

take a look to the ioctl() - function. with this you set the socket nonblocking ...
0
 
ikeworkCommented:
// set socket non-blocking:

int    on = 1;
rc = ioctl(listen_sd, FIONBIO, (char *)&on);
if (rc < 0)
{
   perror("ioctl() failed");
   close(listen_sd);
   exit(-1);
}
0
 
ikeworkCommented:
and the same for windows:
/*
int ioctlsocket(
  SOCKET s,
  long cmd,
  u_long* argp
);
*/

int    on = 1;
rc = ioctlsocket(listen_sd, FIONBIO, (char *)&on);
if (rc < 0)
{
   perror("ioctlsocket() failed");
   close(listen_sd);
   exit(-1);
}
0
 
MysidiaCommented:
Your code doesn't check the return value of  recv() for an error.


Should have something such as...
#include <errno.h>

...
...
 status = ::recv(m_sock, buf, MAXRECV, 0); // this statement causes the hang
if (status == -1 &&   errno !=  EINTR  && errno != EAGAIN) {
    perror("socket");
        break;
}

Use select() to wait for a status change on the socket before performing the recv call.


    char buf[MAXRECV + 1];
    fd_set readset;
    int status, temp;

     while (status != 0)
     {
          FD_ZERO(&readset);
          FD_SET(m_sock, &readset);

          memset(buf, 0, MAXRECV + 1);
          if ((temp = select(m_sock + 1, &readset, NULL, NULL, NULL) )  > 0 ) {                        
              status = ::recv(m_sock, buf, MAXRECV, 0); // this statement causes the hang
              if (status == -1) {
                   perror("recv");
                   break;
              }
          }
          else if (temp == -1) {
               if (errno != EINTR) {  perror("select");  }
          }
     }

You really don't need non-blocking sockets  for a simple interactive client application: turning on
the non-blocking flag is ONE thing, but there are other major changes you would need to make
to properly use a non-blocking socket.

To use a non-blocking socket, you need to flag it non-blocking just after creation and wait for
a positive select()  response on the socket before each operation on the descriptor, including a connect()
or write().

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.