Reputation: 2294
I am trying to make client and server talk and the data being communicated is a vector of structure
std::vector<element> elemvec
which is private member of a class, but we have methods to to retrieve individual elements of that vector using bloom_db.getelem(unsigned int)
.
It is adamantly failing to compile inside boost library code.
I understand that my knowledge on streams, buffers and serialization is highly flawed, but seems I need some hand holding as I don't want to copy code from boost examples.
Following is my code :
typedef struct elem{ //This will be seen as a POD (Plain Old Data) in boost::asio::buffer
bool bit;
int count;
uint64_t hashSum[2];
uint64_t idSum;
template <typename Archive>
void serialize(Archive &ar, const unsigned int version){
ar & bit;
ar & count;
ar & hashSum[0];ar & hashSum[1];
ar & idSum;
}
}element;
void sendData(tcp::socket& socket, boost::asio::const_buffer& data)
{
boost::asio::write(socket,boost::asio::buffer(data));
}
void getData(tcp::socket& socket, boost::asio::mutable_buffer& data)
{
boost::asio::read(socket, data);
}
void netcom_client(int portn, string serverip, bloom_filter& bloom_db){
io_service io_service;
ip::tcp::socket client_socket(io_service);
boost::asio::const_buffer snd_buf;
boost::system::error_code ec;
element snd_elem;
string bufdata;
std::ostringstream os;
boost::archive::text_oarchive out_archive {os}; //archive is connected to global stringstream object
unsigned int i;
client_socket.connect(tcp::endpoint(address::from_string(serverip),portn));
//client sends the data : this loop is to send the data
for(i=0; i< bloom_db.size(); ++i){
::set_elemvec(snd_elem,bloom_db.getelem(i));
out_archive << snd_elem; //element inserted in archive
bufdata = os.str();
snd_buf = boost::asio::buffer(os.str());
sendData(client_socket,snd_buf);
}
cout<<"Sent "<<i<<" elements from client"<<endl<<std::flush;
}
void netcom_server(int portn, bloom_filter& bloom_db){
io_service io_service;
element recv_elem;
char bufdata[sizeof(element)];
boost::system::error_code ec;
bloom_filter recvd_bloomdb(4,"rcvbloom_db",4096);
std::istringstream is(bufdata);
boost::archive::text_iarchive in_archive {is};
unsigned int i;
ip::tcp::socket server_socket(io_service);
tcp::acceptor acceptor_server(io_service,tcp::endpoint(tcp::v4(), portn));
acceptor_server.accept(server_socket);
for(i=0; i<recvd_bloomdb.size(); ++i){
boost::asio::mutable_buffer rcv_buf = boost::asio::buffer((void*)bufdata,sizeof(element));
getData(server_socket, rcv_buf);
in_archive >> recv_elem;
recvd_bloomdb.tailadd_elem(recv_elem);
}
cout<<"Received "<<i<<" elements at server"<<endl<<std::flush;
}
First Line from Error
/usr/include/boost/asio/detail/consuming_buffers.hpp: In instantiation of ‘class boost::asio::detail::consuming_buffers<boost::asio::mutable_buffer, boost::asio::mutable_buffer>’:
/usr/include/boost/asio/impl/read.hpp:45:44: required from ‘std::size_t boost::asio::read(SyncReadStream&, const MutableBufferSequence&, CompletionCondition, boost::system::error_code&) [with SyncReadStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; MutableBufferSequence = boost::asio::mutable_buffer; CompletionCondition = boost::asio::detail::transfer_all_t; std::size_t = long unsigned int]’
/usr/include/boost/asio/impl/read.hpp:64:39: required from ‘std::size_t boost::asio::read(SyncReadStream&, const MutableBufferSequence&) [with SyncReadStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; MutableBufferSequence = boost::asio::mutable_buffer; std::size_t = long unsigned int]’
ibflt.cpp:309:35: required from here
/usr/include/boost/asio/detail/consuming_buffers.hpp:164:5: error: no type named ‘const_iterator’ in
‘class boost::asio::mutable_buffer’
const_iterator;
/usr/include/boost/asio/detail/consuming_buffers.hpp:261:36: error: no type named ‘const_iterator’ in
‘class boost::asio::mutable_buffer’
typename Buffers::const_iterator begin_remainder_;
Upvotes: 0
Views: 981
Reputation: 20936
boost::asio::read
takes as second argument buffer which must satisfy Mutable Buffer Sequence requirements, in 1.65 class mutable_buffers_1
does it, not mutable_buffer
(it will work since 1.66 version).
So change:
void getData(tcp::socket& socket, boost::asio::mutable_buffers_1& data)
{
boost::asio::read(socket, data);
}
and
boost::asio::mutable_buffers_1 rcv_buf = ...
std::ostringstream os;
//...
snd_buf = boost::asio::buffer(os.str()); // [1]
sendData(client_socket,snd_buf);
The above code cannot work, I mean it compiles fine but it will bring you undefined behaviour. Why?
boost::buffer
doesn't make a copy of passed data. It returns just tuple (pointer to data and size of data), underlying data is not copied, buffer
just wraps it.
ostringstream::str()
returns string by COPY, reference. So buffer takes it, wraps into tuple and at the end of full expression this temporary string is destroyed, hence you have dangling reference in tuple returned by buffer
.
Solution?
Create named string:
std::string str = os.str();
snd_buf = boost::asio::buffer(str);
Upvotes: 2