50

How do you make a socket non-blocking?

I am aware of the fcntl() function, but I've heard it's not always reliable.

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
Sachin
  • 20,805
  • 32
  • 86
  • 99

10 Answers10

108

fcntl() has always worked reliably for me. In any case, here is the function I use to enable/disable blocking on a socket:

#include <fcntl.h>

/** Returns true on success, or false if there was an error */
bool SetSocketBlockingEnabled(int fd, bool blocking)
{
   if (fd < 0) return false;

#ifdef _WIN32
   unsigned long mode = blocking ? 0 : 1;
   return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
#else
   int flags = fcntl(fd, F_GETFL, 0);
   if (flags == -1) return false;
   flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
   return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
#endif
}
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
63

You're misinformed about fcntl() not always being reliable. It's untrue.

To mark a socket as non-blocking the code is as simple as:

// where socketfd is the socket you want to make non-blocking
int status = fcntl(socketfd, F_SETFL, fcntl(socketfd, F_GETFL, 0) | O_NONBLOCK);

if (status == -1){
  perror("calling fcntl");
  // handle the error.  By the way, I've never seen fcntl fail in this way
}

Under Linux, on kernels > 2.6.27 you can also create sockets non-blocking from the outset using socket() and accept4().

e.g.

   // client side
   int socketfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

   // server side - see man page for accept4 under linux 
   int socketfd = accept4( ... , SOCK_NONBLOCK);

It saves a little bit of work, but is less portable so I tend to set it with fcntl().

phoenix
  • 7,988
  • 6
  • 39
  • 45
hookenz
  • 36,432
  • 45
  • 177
  • 286
  • Isn't it possible that your internal `fcntl` fails before the external `fcntl` fails? – CMCDragonkai Jan 21 '17 at 13:40
  • 1
    depending on how you write your code you can possibly setup race conditions if you call `fcntl` after you've created the socket....that's why the `SOCK_NONBLOCK` flag was added, so you can atomically create a socket as non blocking – horseyguy Mar 18 '18 at 09:57
  • Beware that `fcntl(socketfd, F_GETFL, 0)` can fail, so check the return value before passing it into the output – Pod Mar 14 '19 at 10:53
  • F_GETFL doesn't require any arguments, consult the manpage. – tripulse Dec 15 '21 at 10:41
23

What do you mean by "not always reliable"? If the system succeeds in setting your socket non non-blocking, it will be non-blocking. Socket operations will return EWOULDBLOCK if they would block need to block (e.g. if the output buffer is full and you're calling send/write too often).

This forum thread has a few good points when working with non-blocking calls.

user
  • 23,260
  • 9
  • 113
  • 101
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 25
    I don't think this is a good answer. You tell him that it should be reliable then post a forum thread that can become quickly out of date. Just my opinion, but someone with your rep I would have thought would be thoughtful enough to provide a more thorough answer than a lazy link and quick comment. – hookenz Mar 11 '14 at 23:22
  • 8
    @Matt Sorry to disappoint. Please note that this answer is four and a half years old. I think my answer reveals my frustration with the question's lack of detail. It's hard to argument with "I've heard that doing it the obvious way is not always reliable". I still think so, not sure how to improve on this. – unwind Mar 12 '14 at 06:59
  • 2
    Yeah I realised later just how old the question was. Thinking it was new because someone else updated it and it came up in the activity list... oops. never mind. – hookenz Mar 12 '14 at 07:12
  • Note from the manpages: "POSIX.1-2001 allows either error [EAGAIN or EWOULDBLOCK] to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities." – jg6 Sep 01 '20 at 20:51
16

fcntl() or ioctl() are used to set the properties for file streams. When you use this function to make a socket non-blocking, function like accept(), recv() and etc, which are blocking in nature will return error and errno would be set to EWOULDBLOCK. You can poll file descriptor sets to poll on sockets.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Siva
  • 711
  • 1
  • 5
  • 8
  • Is there any other way of converting a TCPIP to NON BLOCKING socket. I dont want to rely on these methods may be because of my past experiences – Sachin Oct 09 '09 at 13:39
  • 10
    That **is** the way to convert a socket to non-blocking. If you can be specific on your "past experiences" and why you are convinced that this won't work, maybe we can help you. – Graeme Perrow Oct 09 '09 at 16:40
  • You can pass `SOCK_NONBLOCK` to the `socket` call. – Carlo Wood Dec 14 '19 at 21:21
10

On Linux and BSD you can directly create the socket in non-blocking mode (https://www.man7.org/linux/man-pages/man7/socket.7.html):

int fd = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, res->ai_protocol);
if (fd == -1) {
    perror("socket");
    return -1;
}

When accepting connections you can use the accept4 function to directly accept new connections in non-blocking mode (https://man7.org/linux/man-pages/man2/accept.2.html):

int fd = accept4(lfd, NULL, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (fd == -1) {
    perror("accept4");
    return -1;
}

I don't know why the accepted answer doesn't mention this.

Erik
  • 770
  • 7
  • 4
5

I know it's an old question, but for everyone on google ending up here looking for information on how to deal with blocking and non-blocking sockets here is an in depth explanation of the different ways how to deal with the I/O modes of sockets - http://dwise1.net/pgm/sockets/blocking.html.

Quick summary:

  • So Why do Sockets Block?

  • What are the Basic Programming Techniques for Dealing with Blocking Sockets?

    • Have a design that doesn't care about blocking
    • Using select
    • Using non-blocking sockets.
    • Using multithreading or multitasking
5

If you want to change socket to non blocking , precisely accept() to NON-Blocking state then

    int flags=fcntl(master_socket, F_GETFL);
        fcntl(master_socket, F_SETFL,flags| O_NONBLOCK); /* Change the socket into non-blocking state  F_SETFL is a command saying set flag and flag is 0_NONBLOCK     */                                          

while(1){
    if((newSocket = accept(master_socket, (struct sockaddr *) &address, &addr_size))<0){
                if(errno==EWOULDBLOCK){
                       puts("\n No clients currently available............ \n");
                       continue;
               }
    }else{
          puts("\nClient approched............ \n");
    }

}
Omkar
  • 343
  • 3
  • 12
4

It is sometimes convenient to employ the "send/recv" family of system calls. If the flags parameter contains the MSG_DONTWAIT flag, each call will behave similar to a socket having the O_NONBLOCK flag set.

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Stevereeno
  • 41
  • 1
3

Generally you can achieve the same effect by using normal blocking IO and multiplexing several IO operations using select(2), poll(2) or some other system calls available on your system.

See The C10K problem for the comparison of approaches to scalable IO multiplexing.

Andrey Vlasovskikh
  • 16,489
  • 7
  • 44
  • 62
2

The best method for setting a socket as non-blocking in C is to use ioctl. An example where an accepted socket is set to non-blocking is following:

long on = 1L;
unsigned int len;
struct sockaddr_storage remoteAddress;
len = sizeof(remoteAddress);
int socket = accept(listenSocket, (struct sockaddr *)&remoteAddress, &len)
if (ioctl(socket, (int)FIONBIO, (char *)&on))
{
    printf("ioctl FIONBIO call failed\n");
}
Steve Wranovsky
  • 5,503
  • 4
  • 34
  • 52