
I'm starting using Boost::Asio. I tried to write a simple class to send and receive asynchronously UDP datagrams, following the boost::asio tutorial. The class compiles fine, but it's not working and comes out with an exception about a mutex (which shouldn't be involved I guess). Basically there are two methods: one starts an async_receive_from and the other send packets asynchronously. I first start the receiver, then I try to send a packet to localhost (127.0.0.1). But nothing happens. Here is the code, maybe you may know what's wrong. 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!

The message title a bit missleading: it's not asio that doesn't work, but your application :). Please see the comments below.
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();
You run() io_service that doesn't have any work, so run() exits immediately. Then you enqueue some async.request, and your applciation exits, freeing "msgSrv" object and deleting the io_service and the socket. The request you enqueued is still alive, but an attempt to process it causes crash, because you already deleted all the asio stuff... Note that if io_service had some work (eg, pending async_XXX requests, or asio::work object) before you called run(), it would block until all the work is processed. Please see asio tutorial and examples for more information.

I see... I gave for granted that asio was using its own thread do everything... I've been using other libraries and they were working like this.... Sorry, I've been very quick in jumping around the docs... RTFM! 2009/7/27 Igor R <boost.lists@gmail.com>
The message title a bit missleading: it's not asio that doesn't work, but your application :). Please see the comments below.
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();
You run() io_service that doesn't have any work, so run() exits immediately. Then you enqueue some async.request, and your applciation exits, freeing "msgSrv" object and deleting the io_service and the socket. The request you enqueued is still alive, but an attempt to process it causes crash, because you already deleted all the asio stuff... Note that if io_service had some work (eg, pending async_XXX requests, or asio::work object) before you called run(), it would block until all the work is processed. Please see asio tutorial and examples for more information. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Igor, that doesn't seem correct to me, from what I can tell (by reading the docs, and using it) is that io_service::run() will not return immediately if there is no work. http://eckhart.stderr.org/doc/libasio-doc/reference/a00032.html#c84bed0d1dd0... "The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped."
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Igor R Sent: Monday, July 27, 2009 6:31 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] Why boost::asio doesn't work???
The message title a bit missleading: it's not asio that doesn't work, but your application :). Please see the comments below.
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();
You run() io_service that doesn't have any work, so run() exits immediately. Then you enqueue some async.request, and your applciation exits, freeing "msgSrv" object and deleting the io_service and the socket. The request you enqueued is still alive, but an attempt to process it causes crash, because you already deleted all the asio stuff... Note that if io_service had some work (eg, pending async_XXX requests, or asio::work object) before you called run(), it would block until all the work is processed. Please see asio tutorial and examples for more information. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Igor, that doesn't seem correct to me, from what I can tell (by reading the docs, and using it) is that io_service::run() will not return immediately if there is no work.
http://eckhart.stderr.org/doc/libasio-doc/reference/a00032.html#c84bed0d1dd0...
"The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped."
I don't quite understand how you came to your conclusion from the above quotation, as it states exactly the opposite. But anyway, try and run the following code: #include <boost/asio.hpp> int main() { asio::io_service io; asio::ip::tcp::socket sock(ip); io.run(); }

Igor, that doesn't seem correct to me, from what I can tell (by reading the docs, and using it) is that io_service::run() will not return immediately if there is no work.
http://eckhart.stderr.org/doc/libasio-doc/reference/a00032.html#c84bed
0d1dd061bc71010ba1228439da
"The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped."
I don't quite understand how you came to your conclusion from the above quotation, as it states exactly the opposite. But anyway, try and run the following code:
#include <boost/asio.hpp> int main() { asio::io_service io; asio::ip::tcp::socket sock(ip); io.run(); }
My mistake, I got thrown off by the "or until the io_service has been stopped". Thx.
participants (4)
-
Alex Black
-
Dario Rossi
-
Gotch@
-
Igor R