0
votes

I'm currently having a hard time with boost::asio, specially with the buffers in async_write operations.

When I want to write a packet, I use

async_write(sock_, boost::asio::buffer((char *)&t.getData(), sizeof(T)), boost::bind(&BoostTcpSocket::manageWrite, this, t, boost::asio::placeholders::error));

It works fine if i try to send one packet at the time. However if I make two followed call of async_write, it sends me twice the second packet. I have no problem with the packet life cycle.

I think the problem comes from the buffer, i'd like to have a packetQueue buffer instead of one packet buffer.

How can i do this ? Thanks for your help

EDIT : here is more info about the code :

Here is how it works :

int  BoostTcpSocket::manageWrite(Packet *t, const boost::system::error_code& error)
{
    if (!er)
        std::cout << "Success " << t.getData() << std::endl;
    else
        std::cout << "Error" << std::endl;
    // delete t;  => Packet LifeCycle isn't the problem here...
}

int main()
{
    boost::asio::ip::tcp::socket    sock_(io);
    sock_.connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1", 8080));
    Packet *p = new Packet("data1");
    Packet *p2 = new Packet("data2");

  sock_.async_write(boost::asio::buffer((char *)&p->getData(), sizeof(Packet::data)), boost::bind(&BoostTcpSocket::manageWrite, this, p, boost::asio::placeholders::error));
  sock_.async_write(boost::asio::buffer((char *)&p2->getData(), sizeof(Packet::data)), boost::bind(&BoostTcpSocket::manageWrite, this, p2, boost::asio::placeholders::error));
io.run();
}

This code basically sends me twice the data "data2" even though the output on the server side std::cout is Success data1 Success data2...

EDIT : Apparently i was doing something wrong somewhere else because it is now working.. Thanks everybody for your time & help !

2
I think a bit more code would be helpful to give you some hints. Eg. show us manageWrite(..) - Simon
What does p->getData() return? Why you need the cast? What is Packet? - Simon
p is a class containing a struct. The struct which im trying to send through the socket. - user1040048

2 Answers

2
votes

The data at &t.getData() must remain intact throughout the entire asynchronous operation. You must not overwrite the data there before receiving a call back to BoostUdpSocket::manageWrite with a success indication.

0
votes

You have bound two times *p in your async_write(..) callbacks. This leads to double deletion!

See boost::bind(..., *p, ...)

sock_.async_write(boost::asio::buffer((char *)&p->getData(), sizeof(Packet::data)), boost::bind(&BoostTcpSocket::manageWrite, this, *p, boost::asio::placeholders::error)); 
sock_.async_write(boost::asio::buffer((char *)&p2->getData(), sizeof(Packet::data)), boost::bind(&BoostTcpSocket::manageWrite, this, *p, boost::asio::placeholders::error));

BTW: if you wannt to pass *p as reference, consider using boost::ref(..) or boost::cref(..).

EDIT: The double delete is, i think, not your problem, but passing *p without boost::ref(..) is the problem - since you're deleting an object which is not heap allocated (because it is a copy!).

EDIT2: Oh i see - you have the code corrcted in the meantime. Is there still a runtime error?