2016-02-25 105 views
-1

我已经使用boost_asio实现了udp_client udp_client :: recieve_from()如下所示。boost :: udp socket.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()代码的问题是,recieving一个分组之后

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; 

inspite其中I显式地清除缓冲区。这是什么原因?我该如何解决这个问题?

请在下面找到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

我建议这个问题是不是与升压:: ASIO,但在缓冲区管理器字符串的管理。很难看到这个班级的实际意义。 – EJP

+0

@EJP - 我有两个客户端,服务器实现。 (TCP和UDP).TCP和UDP客户端都使用buffer_manager来管理缓冲区。它是为数据抽象而创建的。我是C++的初学者。这是否有意义? – liv2hak

+1

我不知道。向我们展示实施。它似乎没有做任何有用的字符数组尚未提供。 – EJP

回答

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)); 

下面是一个小例子,demonstratingstd::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_iterator写入ostream,而无需构建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各种缓冲类型到stdout使用write_hex功能并且与一个自定义类型简化写入十六进制到ostream

#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 
1

,你清除缓存的事实事先提供确凿,这个问题是不是在升压:: ASIO,除非你是在暗示,它保留一些未知目的的记忆。

或者:

  1. 发送方在发送数据报复制数据或
  2. 问题出在什么地方你的缓冲区管理器类,可能字符串的东西。

    我没看到这堂课的要点。我建议你像其他人一样使用char数组重写代码。

+0

请告诉我们这是哪个,和/或删除你的问题。 – EJP