DServer Example

/* Shows how to use the DServer class to accept connections and send and receive
  data. We create a new DClient for each connection, and send it a short
  message. Meant to be used with the simpleclient program.
*/

#include "Dasyne.hpp"
#include <iostream>

using namespace std;
using namespace libdasyne;
class Client;

const uint16_t PORT_NUMBER = 5127;//The port number to communicate over
static bool allOK = true; //false if we should stop the server

static DBuffer reply;//a reply to send to clients when they send us data
static vector<Client*> theClients;//a list of clients who've connected

class Client : public DClient
{
    public:
        //constructor, passes the DEngine and an existing connection to DClient
        Client(DEngine *newNetEngine,
               boost::asio::ip::tcp::socket *newSocket) : DClient(newNetEngine, newSocket)
        {
        }//constructor

    private:
        //Event handler called when we receive data from this client
        void receiveHandler(DBuffer &theData)
        {
            cout << "Received: " << theData.toString() << endl;
            send(reply);
        }//receiveHandler

        //Event handler called when a network error occurs and the client
        //disconnects.
        void errorHandler(string message)
        {
            cout << "Client disconnected: " << message << endl;
        }//errorHandler
};//Client

class SimpleServer : public DServer
{
    public:
        //Constructor, takes a pointer to a DEngine and passes it to the
        //parent DServer object
        SimpleServer(DEngine *newNetEngine) : DServer(newNetEngine)
        {
        }//constructor

    private:
        //Event handler, called when a client connects
        void connectHandler(boost::asio::ip::tcp::socket *newSocket)
        {
            Client *newClient = new Client(netEngine, newSocket);

            cout << "A client connected from " << newClient->getRemoteAddress() << endl;
            theClients.push_back(newClient);
        }//connectHandler

        //Event handler, called when there's an error accepting connections
        void errorHandler(string errMsg)
        {
            cout << errMsg << endl;
            allOK = false;
        }//errorHandler
};//SimpleServer

int main(int argc,
         char *argv[])
{
    DEngine netEngine;//calls event handlers for networking classes
    SimpleServer *myServer = new SimpleServer(&netEngine);//listens for client connections
    string userText;//text entered by the user
    int eventsRun = 0;//the number of events dispatched by a call to update()

    //### Bind the listen socket ###
    if (allOK)
    {
        if (!myServer->bind(libdasyne::DA_IPV4, PORT_NUMBER))
        {
            allOK = false;
            cout << "Couldn't bind: " << myServer->getErrMsg() << endl;
        }//if !bind()
    }//if allOK

    //### Ask the user for a message to distribute ###
    if (allOK)
    {
        cout << "Enter a message to be sent to clients: " << endl;
        getline(cin, userText);
        reply.appendString(userText);
    }//if allOK

    //### Start listening for connections ###
    if (allOK)
    {
        if (myServer->startListening())
            cout << "Listening for TCP connections, hit Ctrl-C to exit." << endl;
        else
        {
            allOK = false;
            cout << "Couldn't listen: " << myServer->getErrMsg() << endl;
        }//else startListening()

    }//if allOK

    //### Periodically call event handlers ###
    while (allOK)
    {
        eventsRun = netEngine.update(-1);
        if (eventsRun < 0)
        {
            cout << netEngine.getErrMsg();
            allOK = false;
        }//if eventsRun

        //Sleep if we have nothing to do
        else if (eventsRun == 0)
            DEngine::sleep(1);
    }//while allOK

    //### Free memory ###
    for (unsigned int i = 0; i < theClients.size(); i++)
        delete theClients.at(i);
    theClients.clear();

    delete myServer;

    return 0;
}//main










Back to Contents