Reputation: 141
I'm taking a look at Beej's Guide to Network Programming trying to get my head around the select() function in C. The way that I understood it was that it stops everything that comes after it until one of the file descriptors in one of its sets becomes available due to some external means (e.g. telnet). But what I am finding is that if I have select() in my program (set to indefinite timeout), no output from previous parts of the program - like a printf saying that a socket is bound - are shown until after select returns, but if I comment out the select function then everything prints properly. This is probably something I've messed up earlier on in my program, so this is my code I copied to test it out:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
//sets the address structure
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8888);
server_address.sin_addr.s_addr = INADDR_ANY;
fd_set master_fds;
fd_set read_fds;
int fdmax;
int listener;
int clients[10];
char buffer[256];
//zeros the file descriptor lists
FD_ZERO(&master_fds);
FD_ZERO(&read_fds);
//gets a socket and binds it
listener = socket(AF_INET, SOCK_STREAM, 0);
bind(listener, (struct sockaddr*)&server_address, sizeof(server_address));
printf("listener bound")
//make listener listen
listen(listener, 10);
printf("listening");
//add listener to the faster file descriptor set
FD_SET(listener, &master_fds);
fdmax = listener;
read_fds = master_fds;
select(fdmax + 1, &read_fds, NULL, NULL, NULL);
return 0;
}
It's a bit messy, but I was just double-checking. When I compile and run this, no output is shown until I telnet into it, when all of the above printfs show and the program terminates. Removing the select() makes everything show when it should.
Is there a good reason why this is happening, or have I done something wrong above?
Upvotes: 1
Views: 93
Reputation: 882326
This is almost certainly because the output buffers are not being flushed until sometime after the select
call returns. Your printf
calls do not end with a \n
newline so, even for line-buffering (where it flushes after each line), no flushing will take place.
If you're writing to a terminal device, you can just ensure the newline is sent after each output, and it will be flushed, something like:
printf("listener bound\n"); // or
puts("listener bound");
If you don't want a newline(a), or if you redirecting output so that it will be fully buffered rather than line-buffered (so the newlines won't have an effect), you will have to fflush(stdout)
before entering the select()
.
(a) I suspect you do because you'll otherwise end up with the rather ugly:
listener boundlistening
Upvotes: 3