How do you make a socket non-blocking?
I am aware of the fcntl()
function, but I've heard it's not always reliable.
How do you make a socket non-blocking?
I am aware of the fcntl()
function, but I've heard it's not always reliable.
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
}
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()
.
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.
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.
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.
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?
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");
}
}
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);
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.
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");
}