Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 294
  • Last Modified:

Socket problem: select() not returning when a new connection is available

I am trying to develop a simple socket server application on Linux (RedHat 8.0 Intel, kernel 2.4.18-14). I am using a non-blocking listening socket and check it with select() to see if new connections are available. I have this implemented on Win32 platform, and the whole server works fine. However, on Linux the select() call seems to never return an indication of a new connection.

Following is a reduced sample application that shows the problem. It does select() in 10 loops 500 ms each, but even though I connect during that time, select() still returns 0's. When the 10 loops are done, the sample calls accept(), and the connection is accepted.

Note that the sample code deliberately omits all error checking. For example, normally I would not call accept() if select() fails. But I think this sample illustrates the point quite clearly: connection is available as it gets accept()'ed fine, but still select() does not see the connection.

Any ideas what could be wrong? I think this is quite a basic usage of select() and accept().

The sample code follows:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>

// Some defines from Win32 world.
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
#define SOCKADDR_IN struct sockaddr_in

int main()
{
  SOCKET sd;
  int retval;

  sd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
  // Set socket to non-blocking mode.
  unsigned long Flags;
  Flags = fcntl(sd, F_GETFL, 0);
  Flags = Flags | O_NONBLOCK;
  fcntl (sd, F_SETFL, Flags);

  SOCKADDR_IN LocalAddr;

  // Set server socket's address info.
  LocalAddr.sin_family = AF_INET;
  LocalAddr.sin_port = htons(8541);
  LocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);

  // Bind the socket to the given port.
  if (bind(sd, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR) {
    printf ("bind() failed.\n");
    return (1);
  }

  // Set the socket to listening state.
  retval=listen(sd, SOMAXCONN);
  if (retval) {
    printf ("listen() failed.\n");
  }

  SOCKET newsd;
  SOCKADDR_IN Accepted;
  socklen_t Size;

  // Try accepting a new connection.
  Size=sizeof(Accepted);
  newsd=accept(sd, (struct sockaddr *)&Accepted, &Size);
  if (newsd!=INVALID_SOCKET) {
    printf ("Connection was accepted.\n");
  }
  else {
    printf ("First accept() failed. Starting to poll...\n");
  }

  fd_set fdread;
  int Timeout=10;
  do {
    struct timeval timeout={0,500000};
    int n;

    FD_ZERO (&fdread);
    FD_SET (sd, &fdread);
    n=1;
    retval=select(n, &fdread, NULL, &fdread, &timeout);
    printf ("select() returned %d.\n", retval);
  } while (retval==0 && Timeout--);

  // Try accepting the new connection.
  newsd=accept(sd, (struct sockaddr *)&Accepted, &Size);
  if (newsd!=INVALID_SOCKET) {
    printf ("Connection was accepted.\n");
  }
  else {
    printf ("accept() failed.\n");
  }

  // From here on we don't really care what happens with the socket.
  // (current client keeps it open so that socktest won't be able to
  // bind if run immediately again - this situation fixes itself when
  // the timeout in the client expires).

  close (newsd);
  close (sd);
  pause();  // Let the user exit the app with Ctrl+C.
}


Sample output:

First accept() failed. Starting to poll...
select() returned 0.
select() returned 0.
select() returned 0.
select() returned 0.
select() returned 0.  <== At this point I connect from another computer.
select() returned 0.
select() returned 0.
select() returned 0.
select() returned 0.
select() returned 0.
select() returned 0.
Connection was accepted.  <== The connection is accepted only here.
0
mnoromaa
Asked:
mnoromaa
  • 2
1 Solution
 
ecwCommented:
Don't use a non-blocking socket.
0
 
mnoromaaAuthor Commented:
Any specific reason why I shouldn't use a non-blocking socket? All documentation suggests that non-blocking sockets are usable.
0
 
mikkon987Commented:
> n=1;
> retval=select(n, &fdread, NULL, &fdread, &timeout);

Try:

n=sd+1;

n should be the highest numbered descriptor plus 1, NOT the number of descriptors!
0
 
mnoromaaAuthor Commented:
Indeed, this did the trick!

Thank you!
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now