Boost logo

Boost Users :

Subject: [Boost-users] [asio] sending and receiving binary
From: Wilde, Donald S (donald.s.wilde_at_[hidden])
Date: 2011-07-09 15:47:36


Hello, all -

After starting from scratch again, I've been able to climb into boost::asio and am beginning to get it to work. Please bear with me; I'm still a noob when it comes to reading C++ templates.

I started by building the little asynchronous daytime server into my primary application, and used the asynch client to successfully talk to it. All well and good.

Now, I've built my real message, which is mixed 7-bit ASCII and binary data (counts, checksums, etc.). In experimenting to make it work, I've started changing my code in the server and client to be more like the echo server.

It appears to be accepting the message, but when it tries to respond the async_write() function throws an error:

ERROR: 'system:0' has occurred.

... and I see 'connection reset by peer' on the client side.

I don't THINK it's because I'm sending binary; this is more likely a glitch in my understanding of boost::asio. I'll back up and look at the daytime and echo examples again and try to see what I've messed up, but I thought I'd put this out there as I've been slogging in mud for a few hours now. :)

// ---- server code ----

      // server

        using boost::asio::ip::tcp;

        TCPConnection::TCPConnection(boost::asio::io_service& aIOService)
                : _socket(aIOService) {
        }

        boost::shared_ptr<TCPConnection> TCPConnection::Create(boost::asio::io_service& aIOService) {
                return boost::shared_ptr<TCPConnection>(new TCPConnection(aIOService));
        }

        tcp::socket& TCPConnection::Socket() {
                return _socket;
        }

        void TCPConnection::CheckMessageAndRespond() {
                _message = make_my_daytime_string();
                boost::asio::async_write( _socket,
                                                        boost::asio::buffer(_message),
                                                        boost::bind(&TCPConnection::HandleWrite,
                                                                        shared_from_this(),
                                                                        boost::asio::placeholders::error,
                                                                        boost::asio::placeholders::bytes_transferred));
        }

        void TCPConnection::HandleWrite( const boost::system::error_code& aError,
                                                        std::size_t aNumBytes) {
                std::cerr << "ERROR: '" << aError << "' has occurred." << std::endl;
        }

        std::string TCPConnection::make_my_daytime_string() {
                std::time_t now = std::time(0);
                return std::ctime(&now);
        }
    
        static const int QUERYIPADDR = 2000;
        TCPServer::TCPServer(boost::asio::io_service& aIOService) : _acceptor(aIOService, tcp::endpoint(tcp::v4(), QUERYIPADDR)) {
                StartAccept();
        }

        void TCPServer::StartAccept() {
                boost::shared_ptr<TCPConnection> newconnection = TCPConnection::Create(_acceptor.io_service());
                _acceptor.async_accept( newconnection->Socket(),
                                                boost::bind(&TCPServer::HandleAccept, this, newconnection,
                                                                boost::asio::placeholders::error));
                std::cout << "Extender inquiry server ready for business!" << std::endl;
        }

        void TCPServer::HandleAccept( boost::shared_ptr<TCPConnection> aNewConnection,
                                                const boost::system::error_code& aError) {
                if (!aError) {
                        aNewConnection->CheckMessageAndRespond();
                        StartAccept();
                }
        }

//---- main equiv (within another class) ----------------------

        ExtenderServer::ExtenderServer(TVED::ITVExtenderDeviceHandler* aEDHandler) {
                try {
                        boost::asio::io_service ioservice;
                        TCPServer Server(ioservice);
                        ioservice.run();
                } catch (std::exception& e) {
                        std::cerr << e.what() << std::endl;
                }
        }

//-------- client (extracted code) -------------------------
    
              string message;
          message.reserve(1024);

        ...

        size_t mlen = message.length();
        const char* mptr = 0;
        mptr = message.data();
        // Create new IO network client service
        boost::asio::io_service io_service;
        // Attach a Query Resolver to it
        tcp::resolver resolver(io_service);
        // We will talk to a Well Known Port (currently 2000)
        tcp::resolver::query query(tcp::v4(), argv[3], "2000");
        tcp::resolver::iterator iterator = resolver.resolve(query);

        tcp::socket socket(io_service);
        socket.connect(*iterator);
        boost::system::error_code error;
        size_t lwrite = boost::asio::write(socket, boost::asio::buffer(mptr, mlen));
        if (error) {
            throw boost::system::system_error(error); // Some error occurred.
        }
        cout << "Wrote " << lwrite << " bytes" << endl;
        char buf[1024];
        size_t len;
        while (1) {
            char buf[1024];
            len = socket.read_some(boost::asio::buffer(buf), error);
            if (error == boost::asio::error::eof) {
                cout << "eof" << endl;
                break;
            } else if (error) {
                throw boost::system::system_error(error); // Some other error.
            }
        }
        string response;
        stringstream sbuf (response, stringstream::in | stringstream::out | stringstream::binary);
        sbuf.write(buf, len);
        cout << endl << "Message string server returns: " << endl;
        print_message(&response);
    } catch (std::exception& e) {
        std::cerr << "ERR from faker: " << e.what() << std::endl;
    }
// ---------------------------------run data -----------------------
    
// example data
// as sent by client "faker" program
Message string client sends:
ASCII: I N T C :: :: :: / :: :: :: :: :: :: :: :: 0 0 : 1 3 : 2 0 : f 9 : 2 a : 8 9 | 1 9 2 . 1 6 8 . 0 . 1 0 | 3 0 0 0 F N :: H
Binary: 49 4E 54 43 00 00 00 2F 00 00 00 00 00 00 00 00 30 30 3A 31 33 3A 32 30 3A 66 39 3A 32 61 3A 38 39 7C 31 39 32 2E 31 36 38 2E 30 2E 31 30 7C 33 30 30 30 46 4E 8D 48

Wrote 55 bytes
ERR from faker: Connection reset by peer

TIA for suggestions! :D

-- Don Wilde


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