views:

935

answers:

1

With the following class

the header:

namespace msgSrv {

class endPoint {

public:
    asio::ip::udp::endpoint ep;
    endPoint(std::string ip, int port);

};

class msgSrv {

private:
    asio::ip::udp::socket *asioSocket;
    asio::io_service *asioIoService;
    int listenPort;
    boost::array<char, 1> rcvBuff;
    asio::ip::udp::endpoint lastRcvdPcktEndp;
    char * sbuff;

public:

    boost::condition_variable cond;
    boost::mutex mut;
    msgSrv(int listenPort);
    virtual ~msgSrv();

    void start();
    void pckRcvd(const asio::error_code& error, std::size_t bytes_transferred);
    void sendTo(const char* buff, int len, endPoint ep);
    void sendHnd(const asio::error_code& error, std::size_t bytes_transferred);

};

}

the .cpp

#include "msgSrv.h"

namespace msgSrv {

endPoint::endPoint(const std::string ip, int port) {
    asio::ip::address addr = asio::ip::address::from_string(ip);
    ep = asio::ip::udp::endpoint(addr, port);
}

msgSrv::msgSrv(int listenPort) {
    // TODO Auto-generated constructor stub
    this->listenPort = listenPort;
    try {
     asioIoService = new asio::io_service();
     asioSocket = new asio::ip::udp::socket(*asioIoService,
       asio::ip::udp::endpoint(asio::ip::udp::v4(), listenPort)); //new asio::ip::udp::socket_(*asioIoService, udp::endpoint(udp::v4(), listenPort));
    } catch (std::exception &e) {
     std::cerr << "Error initializing ioservice or socket:" << e.what();
    }
    asioIoService->run();

}

msgSrv::~msgSrv() {
    // TODO Auto-generated destructor stub
    delete asioIoService;
    delete asioSocket;
}

void msgSrv::start() {

    asioSocket->async_receive_from(asio::buffer(rcvBuff), lastRcvdPcktEndp,
      boost::bind(&msgSrv::pckRcvd, this, asio::placeholders::error,
        asio::placeholders::bytes_transferred));

}

void msgSrv::pckRcvd(const asio::error_code& error,
     std::size_t bytes_transferred) {
    std::cout << "Rcvd! " << lastRcvdPcktEndp.address().to_string() << ":"
      << lastRcvdPcktEndp.port() << "\n";
}

void msgSrv::sendTo(const char* buff, int len, endPoint ep) {
    sbuff = new char[len];
    mempcpy(sbuff, buff, len);
    asioSocket->async_send_to(asio::buffer(sbuff, len), ep.ep, boost::bind(
      &msgSrv::sendHnd, this, asio::placeholders::error,
      asio::placeholders::bytes_transferred));

}

void msgSrv::sendHnd(const asio::error_code& error,
     std::size_t bytes_transferred) {
    std::cout << "Snt!\n";

    delete sbuff;
}

}

and the following "main" file:

int main()
{
    msgSrv::msgSrv aa(4450);
    aa.start();
    msgSrv::endPoint ep("127.0.0.1", 4450);
    std::string a("Prova!");
    int len = a.length();
    aa.sendTo(a.c_str(), len, ep);
    std::cout << "sent...\n";
    std::cout << "notified...\n";
}

all I get is:

terminate called after throwing an instance of 'asio::system_error'
  what():  mutex: Invalid argument
sent...
notified...

What's wrong?? I tried even to put a while(1) in the main, to see if something happens... I even tried to put a condition in the main that is unlocked by the receive handler... all remains locked... So what??? No idea!

A: 

I don't see you actually locking any muxtex, so that error is strange.

However your problem is to calling asioIoService->run() inside the constructor, witch fall in infinite loop. The solution is to create a new boost::thread, witch call asioIoService->run() itself. This thread will be processing all jobs. You may also call asio::io_service::run() with more then one thread, to get processing on more then one job at the same time.

m_thread = new boost::thread(boost::bind(&asio::io_service::run,asioIoService));

Calling asioIoService->stop() will force exit of asio::io_service::run(), thus closing the thread. You must join this thread to ensure that thread terminates before destroying asioIoService pointer in the destructor of your msgSrv class.

lionbest
my 7th grade language arts teacher beat us all with a spiked stick till we got this correct ... witch wears a black hat ... which is for choosing. Always spell it as which and you'll be right 90% of the time.
caspin