Boost logo

Boost Users :

Subject: Re: [Boost-users] boost asio async_read_some
From: Chris Freehill (cfreehill_at_[hidden])
Date: 2008-12-07 19:25:43


Igor,

Thanks for the response. I've been out for a few days, so I haven't
been able to reply. Here is a self-contained example that illustrates
the problem. This example creates a echo server thread that should
echo back to the caller anything the caller sends to the thread. (Note
that I have a windows Sleep() in there.) The server thread appears to
do what I expect. The client thread works until the call to
async_read_some(). The call returns, but I never hit the breakpoint I
set in my handler, nor do I see any output from the handler.

Igor, or anyone, please have a look...

Thanks,
Chris

=============================================START==================================================

#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/thread.hpp>

const static unsigned int cMaxLength = 512;
static const std::string cStopEchoCommand("STOP_ECHO");

static boost::asio::io_service ioService; //needs to have the same
life span as socket, or longer
static boost::asio::ip::tcp::resolver lResolver(ioService);

//-------------------------------------------------------------------------------------------------
static int doConnect(std::string& ipAddress, std::string& portNumber,
                  boost::shared_ptr<boost::asio::ip::tcp::socket>& inOutSocket)
{
    using boost::asio::ip::tcp;

    try
    {
        tcp::resolver::query query(tcp::v4(), ipAddress.c_str(), portNumber.c_str());
        tcp::resolver::iterator endpoint_iterator = lResolver.resolve(query);
        tcp::resolver::iterator end;
                
        if (inOutSocket == NULL)
        {
                 boost::shared_ptr<tcp::socket> tmpSocketPtr(new
tcp::socket(ioService));
                inOutSocket = tmpSocketPtr;
        }

        boost::system::error_code error = boost::asio::error::host_not_found;

        while (error && endpoint_iterator != end)
        {
                inOutSocket->close();
                inOutSocket->connect(*endpoint_iterator++, error);
        }

        if (error) {
                return -1;
        }
     }
     catch(...)
        {
                return -1;
        }

        return 0;
}

//Server routine
static void session(unsigned int port)
{
        using boost::asio::ip::tcp;
        boost::asio::io_service io_service;

        tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
        tcp::socket sock(io_service);

        try
        {
                bool done = false;

                a.accept(sock);

                for (;;)
                {
                        char data[cMaxLength];

                        boost::system::error_code error;
                        size_t length = sock.read_some(boost::asio::buffer(data, cMaxLength), error);
                        if (error == boost::asio::error::eof)
                        {
                                // done, stop echoing, wait for another connection
                                break;
                        }
                        else if (error)
                        {
                                std::cerr << "Error while receiving: " <<
                                                        boost::system::system_error(error).what() << "\n";

                                // TODO report failure
                                break; // closing.
                        }
                        else if (length == cStopEchoCommand.length())
                        {
                                //See if it's time to end
                                if (cStopEchoCommand.compare(0, cStopEchoCommand.length(), data))
                                {
                                        break;
                                }
                        }
                        else
                        {
                                //boost::asio::write(sock, boost::asio::buffer(data, length));
                                int bytesWritten = sock.write_some(boost::asio::buffer(data, length));

                                if (bytesWritten == 0)
                                {
                                        std::cerr << "Error while writing to socket: " <<
                                                        boost::system::system_error(error).what() << "\n";
                                }
                        }
                }
                
        }
        catch (std::exception& e)
        {
                // TODO report failure
                std::cerr << "Exception in thread: " << e.what() << "\n";
        }
}

class TestClass
{

public:
   TestClass(std::string ipAddress, std::string
port):mIPAddress(ipAddress), mPort(port)
        {}

        void PollReadhandler(const boost::system::error_code& error, size_t
bytes_transferred)
         {
                mDataReadFromPoll = true;
                boost::system::error_code e;
                std::cout << "DELETE ME; PollReadhandler called()" << "\n";
         }

        void testTCPIP()
        {
                using boost::asio::ip::tcp;

                // Start an separate thread which echoes all trafic to the port.
                std::istringstream i(mPort);
                unsigned int port;
                i >> port;

                mDataReadFromPoll = false;

                boost::thread echoTcpServer(boost::bind(session, port));

                boost::shared_ptr<tcp::socket> socketPtr;

                int ret = doConnect(mIPAddress, mPort, socketPtr);

                if (ret)
                {
                        std::cerr << "Failed to get connection" << std::endl;
                        return;
                }
                //-------------------------------------------------------------------------------------------------
                // test sync. read

                char buffer[512];
                unsigned int bytesRead;
                std::string test1Str("Test 1");

                std::size_t len =
socketPtr->write_some(boost::asio::buffer(test1Str.c_str(),
test1Str.length()));

                Sleep(1000); //Windows

                try
                {
                        int readError = 0;
                        std::vector<unsigned char> readVectorBuffer(32);
                        //unsigned char readVectorBuffer[512];

                        boost::system::error_code e;
                        //unsigned int amtRead =
socketPtr->read_some(boost::asio::buffer(readVectorBuffer, 512), e);
                        unsigned int amtRead =
socketPtr->read_some(boost::asio::buffer(readVectorBuffer, 32), e);
                        if (amtRead != test1Str.length())
                        {
                                std::cerr << "read_some read an unexpected number of bytes" << std::endl;
                                return;
                        }
                        std::string s(readVectorBuffer.begin(),readVectorBuffer.end());
                        std::cout << "read_some returned:" << s << std::endl;

                }
                catch (...)
                {
                        std::cerr << "Problem with read_some" << std::endl;
                }

                //-------------------------------------------------------------------------------------------------
                // test async. read
                std::string test2Str("Test 2");

                len = socketPtr->write_some(boost::asio::buffer(test2Str.c_str(),
test2Str.length()));

                Sleep(1000);

                //Poll
                while (!mDataReadFromPoll)
                {
                        socketPtr->async_read_some(boost::asio::buffer(buffer, 512),
                                                boost::bind(&TestClass::PollReadhandler, this,
                                                        boost::asio::placeholders::error,
                                                        boost::asio::placeholders::bytes_transferred));

                        Sleep(1000);
                }

                //NEVER REACHES HERE
                mDataReadFromPoll = false;

                len = socketPtr->write_some(boost::asio::buffer(cStopEchoCommand.c_str(),
                                                                cStopEchoCommand.length()));

                // Wait until the server thread is finished.
                echoTcpServer.join();

        }
//-------------------------------------------------------------------------------------------------
private:
        std::string mIPAddress;
        std::string mPort;
        bool mDataReadFromPoll;
};

int main()
{
        TestClass testCase("127.0.0.1", "2222");
        testCase.testTCPIP();
}

=============================================END====================================================

---------- Forwarded message ----------
From: "Igor R" <boost.li..._at_[hidden]>
Date: Dec 4, 1:44 am
Subject: boost asio async_read_some
To: BOOST Archives

_______________________________________________
Boost-users mailing list
Boost-us..._at_[hidden]http://lists.boost.org/mailman/listinfo.cgi/boost-users

> Here's a simplified version of my call and handler:

> unsigned char tmpBuffer[512]; //global

> void MyClass::handler(const boost::system::error_code& error, size_t
> bytes_transferred)
> {
> boost::system::error_code e;
> std::cerr << "handler called()" << "\n";
> }

> void MyClass::test()
> {

> ...
> socketPtr->async_read_some(boost::asio::buffer(tmpBuffer, 512),
> boost::bind(&MyClass::handler, this,
> boost::asio::placeholders::error,

> boost::asio::placeholders::bytes_transferred));
> }

> Can anyone give me any idea as to how I can get my handler to be called?

Could you please provide some code-excerpt that should compile and work?
I.e. code that contains socket initialization, io_service run and your
object creation - because the mistake is probably somewhere at those points.

> Invocation of the handler will be performed in a
> manner equivalent to using boost::asio::io_service::post()." I'm not
> sure exactly what this means...what is this equivalent manner that is
> mentioned?

It means that the handler would be invoked in one of the threads that run
the io_service object used by the socked.- Hide quoted text -

- Show quoted text -


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net