I have to make a synchronous chat server using boost. I almost completed the server code, it may be still far away from what it should be, but I got very strange error that I couldn't find anything about in Internet. I really want to fix it before continuing but I don't know how. Here is the code:
#include<iostream>
#include<list>
#include<map>
#include<queue>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<boost/thread.hpp>
#include<boost/bind.hpp>
#include<boost/asio.hpp>
#include<boost/asio/ip/tcp.hpp>
using namespace std;
using namespace boost::asio;
using namespace boost::asio::ip;
typedef boost::shared_ptr<tcp::socket> socket_ptr;
typedef boost::shared_ptr<string> string_ptr;
typedef boost::shared_ptr< list<socket_ptr> > clientList_ptr;
typedef boost::shared_ptr< list<string> > nameList_ptr;
const int THREADS = 1;
io_service service;
tcp::acceptor acceptor(service, tcp::endpoint(tcp::v4(), 30001));
boost::mutex mtx;
clientList_ptr clientList(new list<socket_ptr>);
nameList_ptr nameList(new list<string>);
boost::asio::streambuf buff;
time_t timer;
void error(const char *msg)
{
perror(msg);
exit(1);
}
bool clientSentExit(string_ptr message)
{
return message->find("exit") != string::npos;
}
void disconnectClient(socket_ptr clientSock, const boost::system::error_code& error)
{
boost::system::error_code ec = error;
auto position = find(clientList->begin(), clientList->end(), clientSock);
clientSock->shutdown(tcp::socket::shutdown_both, ec);
clientSock->close(ec);
clientList->erase(position);
cout << "Client Disconnected! " << clientList->size() << " total clients" << endl;
}
void do_processing(socket_ptr sock, const boost::system::error_code& error)
{
if(!clientList->empty())
{
mtx.lock();
boost::asio::streambuf buff;
size_t bytes_transferred = boost::asio::read_until(*sock, buff, '\n');
buff.commit(bytes_transferred);
std::istream istrm(&buff);
string_ptr msg(new string(""));
std::getline(istrm, *msg);
msg->push_back('\n');
buff.consume(buff.size());
if(clientSentExit(msg) || error)
{
disconnectClient(sock, error);
}
else
{
cout << "ChatLog: " << *msg << endl;
for(auto& cliSock : *clientList)
{
if (cliSock->is_open() && cliSock != sock)
{
cout << "Sending: " << time(&timer) << endl;
sock->write_some(buffer(*msg));
}
}
}
mtx.unlock();
}
}
int main(int argc, char *argv[])
{
boost::thread_group threads;
while (true)
{
cout << "Waiting for clients...\n";
socket_ptr clientSock(new tcp::socket(service));
acceptor.accept(*clientSock);
clientList->emplace_back(clientSock);
threads.create_thread(boost::bind(do_processing, clientSock, boost::asio::placeholders::error));
}
threads.join_all();
getc(stdin);
return 0;
}
And here is the error message:
In file included from /sapmnt/HOME/i322722/usr/boost/include/boost/bind.hpp:22:0,
from /sapmnt/HOME/i322722/usr/boost/include/boost/thread/detail/thread.hpp:30,
from /sapmnt/HOME/i322722/usr/boost/include/boost/thread/thread_only.hpp:22,
from /sapmnt/HOME/i322722/usr/boost/include/boost/thread/thread.hpp:12,
from /sapmnt/HOME/i322722/usr/boost/include/boost/thread.hpp:13,
from server.cpp:9:
/sapmnt/HOME/i322722/usr/boost/include/boost/bind/bind.hpp: In instantiation of \u2018void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, const boost::system::error_code&); A = boost::_bi::list0; A1 = boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > >; A2 = boost::arg<1> (*)()]\u2019:
/sapmnt/HOME/i322722/usr/boost/include/boost/bind/bind.hpp:895:50: required from \u2018boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void; F = void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, const boost::system::error_code&); L = boost::_bi::list2<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > >, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]\u2019
/sapmnt/HOME/i322722/usr/boost/include/boost/thread/detail/thread.hpp:116:17: required from \u2018void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void, void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, const boost::system::error_code&), boost::_bi::list2<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > >, boost::arg<1> (*)()> >]\u2019
**server.cpp:218:1: required from here
/sapmnt/HOME/i322722/usr/boost/include/boost/bind/bind.hpp:315:56: error: no match for \u2018operator[]\u2019 (operand types are \u2018boost::_bi::list0\u2019 and \u2018boost::arg<1>()\u2019)
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);**
The numbers in the "required from here" statements are wrong because I have many comments which I want to keep in the IDE, but deleted here. The actual line in which the error occurs is the very last line of the code - with the '}' that closes the main function.
I would be grateful for any answers.
It's fixed now. As they told me, it's something like a confrontation between
const boost::system::error_code& error
and
boost::asio::placeholders::error.
They told me that these error codes are not needed, they are required if the chat server is asynchronous, but here the thread group cannot send an error code.
I'm not sure if I have understood perfectly everything and sorry if the answer seems badly written. Removing the error codes everywhere except for:
boost::system::error_code ec;
fixed the problem.
Related
I am creating a ROS subscriber and trying to use it's data from callback function. I followed the [ROS Q&A] 187 - Unable to use data received in callback function. I am getting the following error
listener: /usr/include/boost/smart_ptr/shared_ptr.hpp:734: typename boost::detail::sp_member_access<T>::type boost::shared_ptr<T>::operator->() const [with T = const std_msgs::String_<std::allocator<void> >; typename boost::detail::sp_member_access<T>::type = const std_msgs::String_<std::allocator<void> >*]: Assertion `px != 0' failed.
Aborted (core dumped)
Code
#include <typeinfo>
#include "ros/ros.h"
#include "std_msgs/String.h"
class Listener
{
public:
std_msgs::String::ConstPtr data; //attribute
void callback(const std_msgs::String::ConstPtr& msg);
};
// %EndTag(CLASS_WITH_DECLARATION)%
void Listener::callback(const std_msgs::String::ConstPtr& msg)
{
data = msg;
}
int main(int argc, char **argv)
{ Listener listener;
ros::init(argc, argv, "listener_class");
ros::NodeHandle n;
// %Tag(SUBSCRIBER)%
ros::Subscriber sub = n.subscribe("chatter", 1000, &Listener::callback, &listener);
// %EndTag(SUBSCRIBER)%
ros::Rate loop_rate(1);
while(ros::ok())
{
std::cout << " Data is " << listener.data->data.c_str() << std::endl;
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
As far as I understand the problem is because of this line std_msgs::String::ConstPtr data as when the subscriber starts it don't get any message for few milliseconds and it's complanning it's empty in a c++ way.
One solution is to remove ConstPtr but by passing a const pointer into the callback, we avoid doing a copy.
Any help would be much appreciated.
You shouldn't be storing a ROS callback message as a String::ConstPointer, you should be storing the message data directly. Such as:
class Listener
{
public:
std::string data; //attribute
void callback(const std_msgs::String::ConstPtr& msg);
};
void Listener::callback(const std_msgs::String::ConstPtr& msg)
{
data = msg->data;
}
After the callback return the message and pointer will be deconstructed
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I was just trying to accept incoming request with acceptor socket and when it enters the async_accept it throws out an error, I'm not sure what is causing the error. The thing is I'm not even sending the request from the client but still it enters the async_accept handler for some reason, here is the part of the code which is causing the error
main.cpp
#include <iostream>
#include "server.hpp"
#include "connection.hpp"
class Connection;
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server.hpp
#pragma once
#include <thread>
#include <boost/asio.hpp>
template <typename Connection>
class Server{
using shared_connection = std::shared_ptr<Connection>;
private:
unsigned short port_;
std::thread io_thread_;
boost::asio::io_context ioc_;
boost::asio::io_context::work work_;
boost::asio::ip::tcp::endpoint endpoint_;
boost::asio::ip::tcp::acceptor acceptor_;
void handle_new_request(shared_connection connection, const system::error_code &ec){
if(!ec){
connection->start_operation();
}else{
error::print(ec);
return;
}
}
public:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port) {
io_thread_ = std::move(std::thread([&]{ ioc_.run(); }));
io_thread_.join();
}
~Server() {
if(acceptor_.is_open())
acceptor_.close();
io_thread_.join();
}
void start(){
using namespace asio::ip;
system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(),ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true),ec);
// binds to the endpoint
acceptor_.bind(endpoint_,ec);
if(!ec){
std::cout << "Listening for requests from port " << port_ << std::endl;
acceptor_.listen();
}else{
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(connection->sock_,[=](system::error_code ec){
handle_new_request(connection,ec);
});
}
};
connection.hpp
#pragma once
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
std::vector<char> buffer_space_;
private:
boost::asio::mutable_buffers_1 buffer_;
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
explicit Connection(boost::asio::io_context &context,const int &size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(),size){}
~Connection(){ if(sock_.is_open()) sock_.close(); }
void start_operation(){
if(sock_.is_open()){
sock_.async_read_some(buffer_,[me = shared_from_this()](const system::error_code &ec, std::size_t bytes){
if(!ec){
for(int i=0;i<bytes;++i)
std::cout << me->buffer_space_[i];
std::cout << std::endl;
me->start_operation();
}else{
error::print(ec);
return;
}
});
}
}
};
error.hpp
#pragma once
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code &ec){
std::cerr << "Error Code : " << ec.value() << ", Message : " << ec.message() << std::endl;
}
}
Any help on this would be appreciated. Thanks!
The error lies in having the io_thread_.run() in the destructor which would destroy the socket object by then
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server will call the deleter, which destroys Server_ on exiting main. You Would like to join any threads or await the shutdown of the server before exiting main.
You would in your case join the iothread, like you TRIED to do.
However, you do it in the server constructor:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port)
{
io_thread_ = std::move(std::thread([&] { ioc_.run(); }));
io_thread_.join();
}
I can't really figure out how this would not hang indefinitely due to the work_. On tangentially related observation is that work_ is NOT initilaized before ioc_ (or thread_) because initialization happens in order of member declaration instead of order in which the initializers appear. You will want to fix the declaration order regardless:
boost::asio::io_context ioc_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::io_context::work work_;
unsigned short port_;
boost::asio::ip::tcp::endpoint endpoint_;
std::thread io_thread_;
Similarly in Connection:
private:
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
private:
std::vector<char> buffer_space_;
boost::asio::mutable_buffers_1 buffer_;
Fixed Demo
Live On Coliru
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code& ec)
{
std::cerr << "Error Code : " << ec.value()
<< ", Message : " << ec.message() << std::endl;
}
}
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
private:
std::vector<char> buffer_space_;
boost::asio::mutable_buffers_1 buffer_;
public:
explicit Connection(
boost::asio::io_context& context, const int& size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(), size)
{
}
void start_operation()
{
if (sock_.is_open()) {
sock_.async_read_some(buffer_,
[me = shared_from_this()](
const boost::system::error_code& ec, std::size_t bytes) {
if (!ec) {
for (size_t i = 0; i < bytes; ++i) {
std::cout << me->buffer_space_[i];
}
std::cout << std::endl;
me->start_operation();
} else {
error::print(ec);
return;
}
});
}
}
};
#include <thread>
#include <boost/asio.hpp>
template <typename Connection> class Server {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context ioc_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work_ {ioc_.get_executor()};
uint16_t port_;
boost::asio::ip::tcp::endpoint endpoint_;
std::thread io_thread_;
void handle_new_request(
shared_connection connection, const boost::system::error_code& ec)
{
if (!ec) {
connection->start_operation();
} else {
error::print(ec);
return;
}
}
public:
explicit Server(uint16_t port)
: acceptor_(ioc_)
, port_(port)
, endpoint_(boost::asio::ip::tcp::v4(), port)
, io_thread_([&] { ioc_.run(); })
{ ; }
~Server()
{
if (acceptor_.is_open()) {
boost::system::error_code ec;
acceptor_.cancel(ec);
//acceptor_.close(ec);
}
work_.reset();
io_thread_.join();
}
void start()
{
using boost::asio::ip::tcp;
boost::system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(), ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true), ec);
// binds to the endpoint
acceptor_.bind(endpoint_, ec);
if (!ec) {
std::cout << "Listening for requests from port " << port_
<< std::endl;
acceptor_.listen();
} else {
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(
connection->sock_, [=, this](boost::system::error_code ec) {
handle_new_request(connection, ec);
});
}
};
#include <iostream>
//#include "server.hpp"
//#include "connection.hpp"
using namespace std::chrono_literals;
class Connection;
int main()
{
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
std::this_thread::sleep_for(4s);
// destructor joins
}
This would give 4s for the first client to connect, and will shut down as soon as all connections are done.
I've put together an asynchronous UDP client (code below) which is throwing the error "vector iterator not dereferenceable" after about 4 seconds of running. There appears to be little information on the exact cause of this error within the boost asio context but it would seem that it may be due to a buffer going out of scope.
I'm using shared pointers and I can't see anywhere that would allow them to go out of scope.
Call stack:
std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 72 C++
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 325 C++
boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > >::operator()() Line 532 C++
[External Code]
boost::asio::detail::buffer_cast_helper(const boost::asio::mutable_buffer & b) Line 146 C++
boost::asio::buffer_cast<void const *>(const boost::asio::mutable_buffer & b) Line 427 C++
boost::asio::detail::buffer_sequence_adapter<boost::asio::const_buffer,boost::asio::mutable_buffers_1>::validate(const boost::asio::mutable_buffers_1 & buffer_sequence) Line 207 C++
boost::asio::detail::win_iocp_socket_send_op<boost::asio::mutable_buffers_1,boost::_bi::bind_t<void,boost::_mfi::mf2<void,client_t,boost::system::error_code const &,unsigned int>,boost::_bi::list3<boost::_bi::value<client_t *>,boost::arg<1>,boost::arg<2> > > >::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned int bytes_transferred) Line 70 C++
boost::asio::detail::win_iocp_operation::complete(boost::asio::detail::win_iocp_io_service & owner, const boost::system::error_code & ec, unsigned int bytes_transferred) Line 46 C++
boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 406 C++
boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164 C++
boost::asio::io_service::run() Line 59 C++
boost::_mfi::mf0<unsigned int,boost::asio::io_service>::operator()(boost::asio::io_service * p) Line 50 C++
boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> >::operator()<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list0>(boost::_bi::type<unsigned int> __formal, boost::_mfi::mf0<unsigned int,boost::asio::io_service> & f, boost::_bi::list0 & a, long __formal) Line 250 C++
boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > >::operator()() Line 1223 C++
boost::detail::thread_data<boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > > >::run() Line 117 C++
boost::`anonymous namespace'::thread_start_function(void * param) Line 303 C++
[External Code]
It looks like it's occurring during the 'do_send' function call 'async_send_to' but the shared pointer is stored in sended so I don't know how that could be getting deleted?
And the class:
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/atomic.hpp>
#include <string>
#include <vector>
namespace asio = boost::asio;
namespace posix_time = boost::posix_time;
namespace lockfree = boost::lockfree;
typedef std::vector<uint8_t> msg_t;
typedef boost::shared_ptr<msg_t> spmsg_t;
typedef boost::shared_ptr<asio::io_service::work> pwork_t;
typedef lockfree::spsc_queue<spmsg_t> msg_queue_t;
struct client_t {
asio::io_service &_svc;
asio::ip::udp::socket _socket;
asio::ip::udp::endpoint _ep;
boost::atomic<bool> _connected;
boost::atomic<bool> _closing;
boost::thread _worker;
pwork_t _work;
msg_queue_t _send_queue;
msg_queue_t _recv_queue;
boost::condition_variable m_cond;
boost::mutex m_Mutex;
client_t(asio::io_service &svc_) :_svc(svc_), _send_queue(1024), _recv_queue(1024), _socket(svc_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)){}
void init(const std::string ip_, const std::string port_) {
_closing = false;
sending = false;
_connected = true;
boost::asio::ip::udp::resolver resolver(_svc);
_ep = *resolver.resolve({ boost::asio::ip::udp::v4(), ip_, port_ });
_work = pwork_t(new asio::io_service::work(_svc));
_worker.swap(boost::move(boost::thread(boost::bind(&asio::io_service::run, &_svc))));
_svc.post(boost::bind(&client_t::do_recv, this));
}
void destroy() {
_work.reset();
_worker.join();
_send_queue.reset();
_recv_queue.reset();
}
bool is_connected() {
return !_closing && _connected;
}
void disconnect() {
_closing = true;
}
boost::atomic<bool> sending;
spmsg_t sended;
void do_send() {
if (_send_queue.pop(sended)) {
_socket.async_send_to(asio::buffer(*sended), _ep, boost::bind(&client_t::handle_sended, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
}
else {
sending.store(false);
if (_closing) {
_socket.shutdown(asio::ip::tcp::socket::shutdown_both);
_socket.close();
_send_queue.reset();
_recv_queue.reset();
_connected = false;
_closing = false;
}
}
}
void handle_sended(const boost::system::error_code &ec_, std::size_t bytes_transferred) {
if (ec_) {
sending.store(false);
printf("%s\n", ec_.message().c_str());
return;
}
do_send();
}
spmsg_t recv_msg;
void do_recv() {
recv_msg = boost::make_shared<msg_t>(2048);
_socket.async_receive_from(asio::buffer(recv_msg->data() + 4, 2044), _ep, boost::bind(&client_t::handle_recv, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
}
void handle_recv(const boost::system::error_code &ec_, std::size_t bytes_transferred_) {
if (ec_) {
printf("%s\n",ec_.message().c_str());
return;
}
*(uint32_t*)recv_msg->data() = bytes_transferred_;
if (_recv_queue.push(recv_msg)) {
m_cond.notify_one();
do_recv();
}
else {
disconnect();
}
}
//spmsg_t get_sended(uint32_t len_) { return spmsg_t(new msg_t(len_ + 4)); }
bool send(unsigned char* msg, int msgSize) {
if (!is_connected())
return false;
spmsg_t msg_ = spmsg_t(new msg_t(msgSize));
memcpy(&msg_->data()[0], msg, msgSize);
if (!_send_queue.push(msg_))
return false;
//send_messages();
return true;
}
bool send_messages() {
if (!is_connected())
return false;
static bool f = false;
if (!sending.compare_exchange_strong(f, true))
return false;
_svc.post(boost::bind(&client_t::do_send, this));
}
spmsg_t recv() {
if (!is_connected())
return NULL;
spmsg_t recved;
if (_recv_queue.pop(recved))
return recved;
else{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_cond.timed_wait(lock, boost::posix_time::milliseconds(5000)))
{
_recv_queue.pop(recved);
return recved;
}
else
return NULL;
}
}
};
I am making an asynchronous UDP client using boost::asio
the send data is OK when receive data that async_receive_from is error
error message: Expression: string iterator not able to de-reference.
What's wrong with my code ?
Can anyone explain. Thanks for a lot.
UDPClient::UDPClient()
: socket_(io_service, udp::endpoint (udp::v4(), 0))
{
receiver_endpoint = boost::asio::ip::udp::endpoint(
boost::asio::ip::address::from_string("127.0.0.1"),
8080);
do_receive();
boost::function0< void> f = boost::bind(&UDPClient::Sendtest,this);
boost::thread t(f);
io_service.run();
}
void UDPClient::do_receive()
{
socket_.async_receive_from(boost::asio::buffer(recv_buffer), receiver_endpoint,
boost::bind(&UDPClient::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void UDPClient::handle_receive(const boost::system::error_code& error, size_t bytes_transferred)
{
std::cout << "recve" << std::endl;
if (!error || error == boost::asio::error::message_size)
do_receive();
}
void UDPClient::Sendtest()
{
while(true)
{
boost::thread::sleep(boost::get_system_time()+boost::posix_time::seconds(10));
str = "23434";
size_t leng = str.length();
socket_.async_send_to( boost::asio::buffer(str,leng) ,
receiver_endpoint,
boost::bind(&UDPClient::handle_write,this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
}
void UDPClient::handle_write(const boost::system::error_code &error,size_t bytes_transferred)
{
cout << "handle_write_over! " << endl;
}
int main()
{
UDPClient updclient;
}
These three lines look like the problem to me:
str = "23434";
size_t leng = str.length();
socket_.async_send_to( boost::asio::buffer(str,leng) ,
Assuming that str is declared as a std::string object, you need to know that std::string is not implicitly convertable to an ASIO buffer.
You might try this:
stocket_.async_send_to(boost::asio::buffer(&str.front(), leng),
Or this ought to compile correctly:
stocket_.async_send_to(boost::asio::buffer(str),
I would note additionally that you've got a different problem in this program, in that you're reusing the buffer before you are certain that the data has been sent. That's beyond the scope of this problem though, and represents a design issue you'll have to address on your own or in a different question.
I am trying to create a class that will read and parse data from a Serial port, however I keep getting an instantiated error and I don't know why. The class takes in a serial port and its io_service. I am using boost. I am getting a ton of errors, but I think its because its cumulative (I think, I am not sure if that is correct). Here is the first one:
In file included from /usr/include/boost/bind.hpp:22:0,
from ../Sources/Magnetic Compensator Core.cpp:17:
/usr/include/boost/bind/bind.hpp: In instantiation of ‘boost::_bi::result_traits&, const boost::system::error_code&, unsigned int)>’:
/usr/include/boost/bind/bind_template.hpp:15:48: instantiated from ‘boost::_bi::bind_t&, const boost::system::error_code&, unsigned int), boost::_bi::list4, boost::reference_wrapper >, boost::arg<1>, boost::arg<2> > >’
Here is the code for the class:
class mag_serial
{
bool data_available;
boost::asio::serial_port& ser_port;
boost::asio::deadline_timer timeout;
char my_buffer[1];
std::string str;
std::string st;
void read_callback(bool& data_available, boost::asio::deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred)
{
data_available = true;
if(str.length() > 1)
{
if (!(str.at(str.length() - 1) == temp))//&str.at(str.length() - 1) != "#")
{
str.append(my_buffer,bytes_transferred);
if(str.at(str.length() - 1) == quit)
{
cout << "I am quitting";
Stop();
ser_port.cancel();
ser_port.close();
return;
}
i++;
}
else if (str.at(str.length() - 1) == temp)
{
st = str;//.substr(1, str.size());
// Processing Functions
}
}
else
{
str.append(my_buffer,bytes_transferred);
if(str.at(0) == quit)
{
cout << "I am quitting";
Stop();
ser_port.cancel();
ser_port.close();
return;
}
}
ser_port.async_read_some(boost::asio::buffer(my_buffer),
boost::bind(&mag_serial::read_callback, boost::ref(data_available),
boost::ref(timeout),boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
data_available = true;
}
void wait_callback(boost::asio::serial_port& ser_port, const boost::system::error_code& error)
{
if (error)
{
// Data was read and this timeout was cancelled
return;
}
}
public:
mag_serial(boost::asio::serial_port& ser_port, boost::asio::io_service& io_svc): ser_port(ser_port), timeout(ser_port.get_io_service()){}
void read_mag_serial_thread()
{
bool data_available = false;
ser_port.async_read_some(boost::asio::buffer(my_buffer),
boost::bind(&mag_serial::read_callback, boost::ref(data_available),
boost::ref(timeout),boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
timeout.expires_from_now(boost::posix_time::seconds(1));
timeout.async_wait(boost::bind(&mag_serial::wait_callback, boost::ref(ser_port),boost::asio::placeholders::error()));
io_svc.run();
if(!data_available)
{
ser_port.close();
cout << "ser_port was closed";
}
}
};
This won't compile
ser_port.async_read_some(boost::asio::buffer(my_buffer),
boost::bind(&mag_serial::read_callback, boost::ref(data_available),
boost::ref(timeout),boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
the member function mag_serial::read_callback needs an instance to bind to.
ser_port.async_read_some(
boost::asio::buffer(my_buffer),
boost::bind(
&mag_serial::read_callback,
this,
boost::ref(data_available),
boost::ref(timeout),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
Here's a coliru, I didn't attempt to fix the formatting.