I made a small client/server program where the server can handle multiple clients at the same time using the select() function. When I run my program everything works fine until I kill a client program, when I kill a client program the server doesn't block at select() but it just iterates in the while loop.
When I change the FD_SETSIZE in select(FD_SETSIZE, ©Fds, NULL, NULL, NULL); to master_socket + 1 it doesn't block so it works fine.
The GNU library says: The select function checks only the first nfds file descriptors. The usual thing is to pass FD_SETSIZE as the value of this argument. https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
Why do I get this bug? How can I pass in FD_SETSIZE and still let the program to block at select()?
Server:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
int main()
{
system("clear");
printf("***SERVER STARTED***\n");
char message[125] = "Welcome to my server";
int master_socket = socket(AF_INET, SOCK_STREAM, 0);
fd_set masterFds, copyFds;
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8888);
socklen_t addrlen = sizeof address;
bind(master_socket, (struct sockaddr *)&address, sizeof(address));
listen(master_socket, 1);
FD_ZERO(&masterFds);
FD_SET(master_socket, &masterFds);
while (1)
{
copyFds = masterFds;
printf("Monitoring for connections...\n");
select(FD_SETSIZE, ©Fds, NULL, NULL, NULL); // When a socket wants to connect it's file descriptor gets stored in copyFds
for (int i = 0; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, ©Fds))
{
if (i == master_socket) // New connection
{
int accepted_socket = accept(master_socket, (struct sockaddr *)&address, &addrlen);
FD_SET(accepted_socket, &masterFds);
printf("[+] New connection accepted\n");
write(accepted_socket, message, sizeof(message)); // Send message to client
}
else
{
// Not finished yet
}
}
}
printf("End of while loop\n");
}
}
Client (same headers):
int main()
{
system("clear");
int clientSocket = socket(AF_INET, SOCK_STREAM, 0), x;
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(8888);
serverAddress.sin_addr.s_addr = INADDR_ANY;
connect(clientSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
char serverResponse[125];
read(clientSocket, serverResponse, sizeof(serverResponse));
printf("test: %s\n", serverResponse);
scanf("%d", &x);
close(clientSocket);
}