我使用boost_asio
实现了一个udp_client。下面给出了udp_client :: recieve_from()。
void udp_client::recieve_from()
{
for(unsigned int i = 0; i < m_buffer_manager.get_recieve_array().size(); ++i)
m_buffer_manager.get_recieve_array()[i] = 0;
/*Initialize our endpoint*/
size_t len = m_socket.receive_from(
boost::asio::buffer(m_buffer_manager.get_recieve_array()), m_sender_endpoint);
m_buffer_manager.message_buffer(m_buffer_manager.get_recieve_array(),len);
std::cout << "Length of recieved message " << len << std::endl;
/*dumps the message into std::cout for debugging.*/
std::cout << m_buffer_manager.get_message_string() << std::endl;
//std::cout.write((const char*)&m_buffer_manager.get_recieve_array()[0], len);
packet_t ack_packet = { "ACK", {} };
auto buffer = ack_packet.serialize();
m_socket.send_to(boost::asio::buffer(buffer), m_endpoint);
}
udp_client.hpp
文件如下所示。
class udp_client
{
public:
udp_client(boost::asio::io_service& io_service,const std::string& host,const std::string& port);
~udp_client();
void subscribe();
void publish(const std::string& message);
void recieve_from();
private:
boost::asio::io_service& m_io_service;
boost::asio::ip::udp::udp::socket m_socket;
boost::asio::ip::udp::udp::endpoint m_endpoint;
boost::asio::ip::udp::endpoint m_sender_endpoint;
buffer_manager m_buffer_manager;
};
用于管理接收缓冲区的buffer_manager
对象如下所示。
class buffer_manager
{
public:
typedef boost::array<unsigned char, 4096> m_array_type;
buffer_manager();
~buffer_manager();
void message_buffer(m_array_type &recv_buf,size_t size);
buffer_manager::m_array_type & get_recieve_array();
std::string & get_message_string();
private:
std::string m_message;
m_array_type m_recv_buf;
};
我的udp_client :: recieve_from()代码的问题是
size_t len = m_socket.receive_from(boost::asio::buffer(m_buffer_manager.get_recieve_array()), m_sender_endpoint);
返回1个数据包。当它收到两个数据包时,它会收到整个两个数据包。 (即第二个数据包的内容被附加到第一个数据包的内容。)
这是暂时的
for(unsigned int i = 0; i < m_buffer_manager.get_recieve_array().size(); ++i)
m_buffer_manager.get_recieve_array()[i] = 0;
我明确地清除了缓冲区。这是什么原因?我该如何解决这个问题。?
请在下面找到buffer_manager.cpp的实现。
#include <iostream>
#include <boost/array.hpp>
#include <boost/algorithm/hex.hpp>
#include <algorithm>
#include "buffer_manager.hpp"
buffer_manager::buffer_manager()
{
}
buffer_manager::~buffer_manager()
{
}
void buffer_manager::message_buffer(m_array_type &recv_buf,size_t size)
{
auto it = recv_buf.begin();
std::advance(it,size);
boost::algorithm::hex(recv_buf.begin(), it, back_inserter(m_message));
}
buffer_manager::m_array_type& buffer_manager::get_recieve_array()
{
return m_recv_buf;
}
std::string & buffer_manager::get_message_string()
{
return m_message;
}
答案 0 :(得分:1)
您事先清除缓冲区这一事实最终确定问题不在于boost :: asio,除非您建议它为某些未知目的保留内存。
或者:
问题出在缓冲区管理器类中,可能是字符串。
我没有看到这堂课的重点。我建议你像其他人一样使用char数组重写代码。
答案 1 :(得分:1)
receive_from()
操作正常运行,不会将数据附加到缓冲区的末尾。另一方面,buffer_manager::message_buffer()
在每次调用时附加到m_message
,因为它使用back_insert_iterator
并且从不清除字符串。
void buffer_manager::message_buffer(...)
{
auto it = recv_buf.begin();
std::advance(it, size);
boost::algorithm::hex(recv_buf.begin(), it, back_inserter(m_message));
// ^~~ invokes m_message.push_back() for the
// range [recv_buf.begin(), it).
}
要解决此问题,请考虑事先清除字符串。
void buffer_manager::message_buffer(...)
{
auto it = recv_buf.begin();
std::advance(it, size);
m_message.clear();
boost::algorithm::hex(recv_buf.begin(), it, back_inserter(m_message));
以下是最小示例demonstrating std::back_inserter
:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
int main()
{
std::string message = "abc";
auto inserter = back_inserter(message);
inserter = 'd';
inserter = 'e';
assert("abcde" == message);
}
我不清楚buffer_manager
提供了什么价值。但是,如果要打印缓冲区的十六进制值,请考虑使用ostream
写入ostream_iterator
,而无需构建string
的开销。例如,以下实用程序函数将迭代器范围的十六进制值写入提供的ostream
:
template <typename Iterator>
void write_hex(Iterator first, Iterator last, std::ostream& out)
{
boost::algorithm::hex(first, last, std::ostream_iterator<char>(out));
}
及其用法:
unsigned char data[3] = { 0, 10, 255 };
write_hex(std::begin(data), std::end(data), std::cout); // writes 000AFF to stdout.
这是一个完整的示例demonstrating使用write_hex
函数将各种缓冲区类型的十六进制值打印到stdout,并使用自定义类型简化将十六进制写入ostream
:< / p>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/hex.hpp>
// Utility funciton to write hex to a stream.
template <typename Iterator>
void write_hex(Iterator first, Iterator last, std::ostream& out)
{
boost::algorithm::hex(first, last, std::ostream_iterator<char>(out));
}
namespace detail {
// Utility type to write an iterable as hex to a stream via the insertion
// operator.
template <typename Iterable>
struct hex_writer
{
const Iterable& iterable;
friend std::ostream& operator<<(std::ostream& stream, const hex_writer& object)
{
write_hex(std::begin(object.iterable), std::end(object.iterable), stream);
return stream;
}
};
} // namespace detail
// Auxiliary function to create hex_writers. Intended to be used for
// chaining writes to an ostream.
template <typename Iterable>
detail::hex_writer<Iterable> as_hex(const Iterable& iterable)
{
return {iterable};
}
int main()
{
// Using c-array.
{
unsigned char data[3] = { 0, 10, 255 };
write_hex(std::begin(data), std::end(data), std::cout);
std::cout << " " << as_hex(data) << std::endl;
}
// Using c++-array.
{
std::array<unsigned char, 3> data = {{ 0, 10, 255 }};
write_hex(begin(data), end(data), std::cout);
std::cout << " " << as_hex(data) << std::endl;
}
// Using vector.
{
std::vector<unsigned char> data = { 0, 10, 255 };
write_hex(begin(data), end(data), std::cout);
std::cout << " " << as_hex(data) << std::endl;
}
}
输出:
000AFF 000AFF
000AFF 000AFF
000AFF 000AFF