I'm just going to check if anyone has any experience with Boost Asio here...
I can't get asynchronous I/O to work properly...
This code may be a little long, but it is simple:
The problem is basically that at the SECOND client connection, the send complete handler is never run (handle_send_complete). Instead, the wait times out. See XSocket::send.Code:#include <memory> #include <algorithm> #include <windows.h> #include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/lexical_cast.hpp> #include <boost/cstdint.hpp> #include <boost/scope_exit.hpp> #include <boost/bind.hpp> using namespace boost; using asio::ip::tcp; namespace ip = asio::ip; class tcp_connection { protected: std::shared_ptr<tcp::socket> m_socket; public: tcp_connection(asio::io_service& io_service): m_socket(new tcp::socket(io_service)) {} tcp::socket& get_socket() { return *m_socket; } }; void handle_request(tcp_connection& connection, const boost::system::error_code& err); int APIENTRY _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int /*nCmdShow*/) { asio::io_service io_service; tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 1)); for (;;) { tcp_connection connection(io_service); boost::system::error_code err; acceptor.accept(connection.get_socket(), err); boost::thread thread(&handle_request, connection, err); } } std::vector<tcp::endpoint> g_SmsGenerators; const char MsgSmsNotAvailable = 1; const char MsgReplyOk = 5; // Data was recieved; OK to send more now class XSocket { public: XSocket(tcp::socket& socket): m_socket(socket) { m_Event = CreateEvent(nullptr, FALSE, FALSE, L""); } template<typename T> void send(const T& data, boost::uint32_t Timeout) { const T _data[1] = { data }; //m_socket.get_io_service().run(); asio::async_write(m_socket, asio::buffer(_data), boost::bind(&XSocket::handle_send_complete, this, _1, _2)); m_socket.get_io_service().run(); unsigned long status = WaitForSingleObject(m_Event, Timeout * 1000); m_socket.cancel(); } private: void handle_send_complete(const boost::system::system_error& err, std::size_t bytes) { SetEvent(m_Event); } public: template<typename T> T get() { std::vector<char> buf(1024); m_socket.receive(asio::buffer(buf)); char reply[1] = { MsgReplyOk }; m_socket.send(asio::buffer(reply)); return boost::lexical_cast<T>(&buf[0]); } protected: tcp::socket& m_socket; HANDLE m_Event; }; void handle_request(tcp_connection& connection, const boost::system::error_code& err) { XSocket socket(connection.get_socket()); auto data = socket.get<int>(); switch (data) { case MsgRequestSms: socket.send(MsgSmsNotAvailable, 10); } }
What is worse, on the THIRD client connection, it sees that the handler for the second write is complete and calls handle_send_complete. However, by then, the associated instance of XSocket is long gone, and it crashes horribly.
What I don't understand is how to make sure that bloody library calls handle_send_complete EVERY time the send finishes. It's obviously important.
Any insight whatsoever would be appreciated.



1Likes
LinkBack URL
About LinkBacks




Sorry for rambling, and good luck!