Recently, I was researching a more efficient way for creating a TCP/IP server to handle multiple clients at once. I have used select() in the past, and that was probably the best thing I could find. I eventually came up with kqueue(), which is a way to asynchronously handle multiple sockets(or file descriptors). From what I read, it seemed to be a very efficient way to handle many clients. The only problem was that there was little information available for how to implement kqueue() in a sockets environment. Due to the lack of information I found, I thought it would be nice to share what I have learned.
I have created 2 classes that you can inherit, to add kqueue() functionality to your server program. The classes are ServerSocket and SocketClient. The ServerSocket class is the heart of the server, it handles all the clients, and does all the hard kqueue() stuff for you. The SocketClient class is what you inherit so that you can control the different socket events. Here are the methods you should implement when inheriting ServerSocket and SocketClient.
ServerSocket:
SocketClient *createClient(); - You MUST implement this method. It is a pure virtual function in the base class. Basically for this method, you just need to return a class that inherits from SocketClient. For example:
SocketClient *ServerSocketDemo::createClient()
{
return new SocketClientDemo();
}
SocketClient: The following methods are all optional, but you probably want to implement them, or else what is the point?
void OnConnect(); - Called when client connects void OnDisconnect(); - Called when client disconnects void OnReceiveData(unsigned char *buffer, int length); - Called when data has been received void OnSendError(int errorNumber); - Called if there was an error sending data
When using the SocketClient class, there are also a few methods you can call, which are:
void sendData(unsigned char *buffer, int length); - Send buffer to client void disconnectClient(); - Disconnect the client
With these classes you should be able to get a basic kqueue() server running. It is relatively limited right now, but still has the core features in it. I will probably extend it more as I start using it more myself.
Here is a zip file with the classes, and a demo of extending the 2 classes:
Below is an excerpt from SocketClientDemo.cpp that shows how to use the classes:
#include "SocketClientDemo.h"
#include <iostream>
using namespace std;
void SocketClientDemo::OnConnect()
{
cout << "Client " + ip + " connected.\n";
}
/*-------------------------------------------------------------*/
void SocketClientDemo::OnDisconnect()
{
cout << "Client " + ip + " disconnected.\n";
}
/*---------------------------------------------------------------------------*/
void SocketClientDemo::OnReceiveData(unsigned char *buffer, int length)
{
printf("Received data, length: %d\n", length);
for(int x = 0; x < length; x++) {
printf("%c", buffer[x]);
}
char *msg = "Good bye!\n";
this->sendData((unsigned char*)msg, strlen(msg)+1);
this->disconnectClient();
}
/*---------------------------------------------------------------------------*/
[tags]kqueue,cpp,sockets[/tags]