Now consider the following server.
- This is a program that implements a nonblocking server that happily serves up a copy of the server code itself to the client.
- A full copy of the program is right here.
- And here's a copy of the program right here:
static const unsigned short kDefaultPort = 12345;
static const string kFileToServe("expensive-server.cc");
int main(int argc, char *argv[]) {
int serverSocket = createServerSocket(kDefaultPort);
if (serverSocket == kServerSocketFailure) {
cerr << "Could not start server. Port " << kDefaultPort << " is probably in use." << endl;
return 0;
}
setAsNonBlocking(serverSocket);
cout << "Static file server listening on port " << kDefaultPort << "." << endl;
list<OutboundFile> outboundFiles;
size_t numConnections = 0;
size_t numActiveConnections = 0;
while (true) {
int clientSocket = accept(serverSocket, NULL, NULL);
if (clientSocket == -1) {
assert(errno == EWOULDBLOCK);
} else {
OutboundFile obf;
obf.initialize(kFileToServe, clientSocket);
outboundFiles.push_back(obf);
cout << "Connection #" << ++numConnections << endl;
cout << "Queue size: " << ++numActiveConnections << endl;
}
auto iter = outboundFiles.begin();
while (iter != outboundFiles.end()) {
if (iter->sendMoreData()) {
++iter;
} else {
iter = outboundFiles.erase(iter);
cout << "Queue size: " << --numActiveConnections << endl;
}
}
}
}
- The implementation of setAsNonBlocking is UNIX gobbledygook, and it's right here:
void setAsNonBlocking(int descriptor) {
int flags = fcntl(descriptor, F_GETFL);
if (flags == -1) flags = 0; // if first call to fcntl fails, just go with 0
fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); // preserve other set flags
}