/* 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 runProgram = 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

static DEngine netEngine;//calls event handlers for networking classes
static DServer *myServer = new DServer(&netEngine);//listens for client connections

//_______________ Client class, one per connection _______________

class Client : public DClient
{
    public:
        //constructor, passes the DEngine and an existing connection to DClient
        Client(boost::asio::ip::tcp::socket *newSocket) : DClient(&netEngine, newSocket)
        {
            setReceiveHandler(boost::bind(&Client::receiveHandler, this, _1));
            setErrorHandler(boost::bind(&Client::errorHandler, this, _1, _2));
        }//constructor

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

        //Event handler called when a network error occurs.
        void errorHandler(string message,
                          bool socketOK)
        {
            if (!socketOK)
                cout << "Client disconnected: " << message << endl;
            else
                cout << message << endl;
        }//errorHandler
};//Client

//_______________ DServer Event Handlers _______________

//Called when a client connects
void connectHandler(boost::asio::ip::tcp::socket *newSocket)
{
    Client *newClient = new Client(newSocket);

    cout << "A client connected!" << endl;
    theClients.push_back(newClient);
}//connectHandler

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

//_______________ Main Function _______________

int main(int argc,
         char *argv[])
{
    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 (!myServer->bind(libdasyne::DA_IPV4, PORT_NUMBER))
    {
        runProgram = false;
        cout << "Couldn't bind: " << myServer->getErrMsg() << endl;
    }//if !bind()

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

    //### Start listening for connections ###
    if (runProgram)
    {
        myServer->setErrorHandler(&errorHandler);
        if (myServer->startListening(&connectHandler))
            cout << "Listening for TCP connections, hit Ctrl-C to exit." << endl;
        else
        {
            runProgram = false;
            cout << myServer->getErrMsg() << endl;
        }//else startListening()
    }//if runProgram

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

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

    //### Delete the objects that use DEngine before it's deleted ###
    for (unsigned int i = 0; i < theClients.size(); i++)
        delete theClients.at(i);

    delete myServer;

    return 0;
}//main











Back to Contents