0

I'm trying to write a server in C, with I/O non-blocking because sometimes it goes down for flood requests. Looking around, I've notice that I/O non-blocking can solve my problem. Reading the Beej guide, I've implemented the recvtimeout function, that set a timeout to handle data from a client. People told me I have to use the select to avoid this problem, but I used it already in the function recvtimeout:

int Server::recvtimeout(int s, char *buf, int len, int timeout)
    {

    //Check if non-blocking
    fcntl(s, F_SETFL, O_NONBLOCK);
int flags = fcntl(s, F_GETFD);
if ((flags & O_NONBLOCK) == O_NONBLOCK) {
  fprintf(stderr, "nonblocking active");
}
else {
  fprintf(stderr, "nonblocking not active");
}
    //End check

fd_set fds;
int n;
struct timeval tv;
// set up the file descriptor set
FD_ZERO(&fds);
FD_SET(s, &fds);
// set up the struct timeval for the timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
// wait until timeout or data received
n = select(s+1, &fds, NULL, NULL, &tv);
if (n == 0){
    return -2; // timeout!
}
if (n == -1){
    return -1; // error
}
// data must be here, so do a normal recv()
return recv(s, buf, len, 0);
    }

So, I've added a piece of code that show me if NONBLOCK is set or not, but never I read nonblocking active, so in my code nonblocking is not active. How can I mod my code to enable this?

The problem is when I read a string from a client and have a code like this:

        char headerstring[512];
    memset(headerstring,0,512);
    if(this->recvtimeout(client_fd,headerstring,sizeof(headerstring),10) < 0){
        close(client_fd);
    }

All works fine, but with a flooder that close the connection during the transaction, the server goes down. I've tried try-catch and any other things...but nothing.

user840718
  • 1,563
  • 6
  • 29
  • 54
  • *Reading the Beej guide, ....* Are you referring to that kid at Chico State who wrote that neat IPC tutorial back in the 1990s? Beej (Brian Hall?) isn't a kid any more, I suppose (come to think of it, neither am I), but I had no idea that anyone still remembered that tutorial. – thb May 29 '12 at 16:30
  • I dunno, but my code works fine with that book, doesn't depend from oldness because unix socket are in early sixty. – user840718 May 29 '12 at 16:35
  • Beej made that tutorial a book, did he? I hadn't known that. I remember it as a web page at Chico State U. In fact, I was so impressed with the web page that I cached a copy of it, and still keep the copy handy. Beej had the page posted up alongside his Internet Pizza Server, as I recall. – thb May 29 '12 at 16:42
  • talking about this? http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html – ShinTakezou May 29 '12 at 19:26

2 Answers2

1

The normal way to set a socket to non-blocking is

  int x;
  x=fcntl(s,F_GETFL,0);
  fcntl(s,F_SETFL,x | O_NONBLOCK);

In your code you are getting the flags using

int flags = fcntl(s, F_GETFD);

whereas you should be doing as

  x=fcntl(s,F_GETFL,0);

So, non-blocking may actually be getting enabled on your socket.

Jay
  • 24,173
  • 25
  • 93
  • 141
0

There are a couple of things:

  1. After select() call:

    if(n < 0) continue;
    if(FD_ISSET(s, &fds)) { //check if Socket ready for reading
       FD_CLR(s, &fds);  // Clear for next time
       // call recv()
    }
    
  2. Set socket as non-blocking like this:

    /* set socket as non-blocking */
    int x = fcntl(s, F_GETFL, 0);
    fcntl(s, F_SETFL, x | O_NONBLOCK);
    
tijko
  • 7,599
  • 11
  • 44
  • 64
Groovy
  • 516
  • 5
  • 16