首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用boost asio在C++中发送layer2

用boost asio在C++中发送layer2
EN

Stack Overflow用户
提问于 2017-09-19 10:31:19
回答 1查看 1.2K关注 0票数 0

当前的UDP宿/源块使用GNURadio向/从NIC发送数据包。它使用boost asio进行发送/接收。我需要修改这些UDP接收器/源块来处理现有功能的UDP和IP,以通过1 1GB的nic,以及添加boost原始套接字/协议,以便我们可以在没有IP地址的10G nic上发送无IP的layer2数据包(接收器是具有自定义错误检查/恢复等功能的FPGA )。

仅使用C语言,我就有了测试程序,在这些程序中,我可以按照自己的需要制作数据包,然后在另一端发送和接收。它们来自:

Create a layer 2 / ethernet socket with boost asio raw socket (in C++) http://qiita.com/kadopoly/items/acafa01945e5cfe39270

因为GNURadio在C++中,所以我需要修改boost套接字/协议设置,以适应udp_sink_impl.cc和udp_sink_impl.h文件,这样我就可以发送数据包。

堆栈溢出链接似乎是最直接的(我不是一个有经验的程序员),我能够将它添加到我的GNURadio块中并进行传输。它不能正确地发送transmitbuffer2缓冲区(发送了一个包,但内容错误),但确实发送了Hello World!streambuf buffer是否正确,所以我不知道。它不能处理0x00,所以我不能用它来测试发送的MAC地址。

这是我目前所拥有的:

udp_sink_impl.h代码片段:

代码语言:javascript
复制
    char tmpHeaderBuff[12];  // 32-bit sync word (0xFFFFFFFF), 32-bit sequence num and 32-bit data size

    unsigned char custom_type[2] = {0x82,0x00};
    unsigned char ethHeader[12] = {0x00,0x0c,0x29,0x05,0x0d,0x15,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
    unsigned char mac_str[6];

    unsigned char dstMAC[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};    
    unsigned char srcMAC[6];

/* 1G management stuff */
        boost::asio::io_service d_io_service;
        boost::asio::ip::udp::endpoint d_endpoint;
        boost::asio::ip::udp::socket *udpsocket;
/* 1G management stuff */

/* 10G raw socket stuff */    
      typedef boost::asio::generic::raw_protocol raw_protocol_t;
      typedef boost::asio::generic::basic_endpoint<raw_protocol_t> raw_endpoint_t;      
      boost::asio::io_service d_io_service10;

      raw_protocol_t::socket *d_socket10;
/* 10G raw socket stuff */

udp_sink_impl.cc代码片段:

代码语言:javascript
复制
  getMACAddress(d_send_iface,srcMAC);

/* Begin 1G management connection */
      std::string s__port = (boost::format("%d") % port).str();
      std::string s__host = host.empty() ? std::string("localhost") : host;
      boost::asio::ip::udp::resolver resolver(d_io_service);
      boost::asio::ip::udp::resolver::query query(s__host, s__port,
          boost::asio::ip::resolver_query_base::passive);
      d_endpoint = *resolver.resolve(query);

          udpsocket = new boost::asio::ip::udp::socket(d_io_service);
        udpsocket->connect(d_endpoint);
/* End 1G management connection */

/* Begin 10G management connection */      
      sockaddr_ll sockaddr;
      memset(&sockaddr, 0, sizeof(sockaddr));
      sockaddr.sll_family = PF_PACKET;
      sockaddr.sll_protocol = htons(ETH_P_ALL);
      sockaddr.sll_ifindex = if_nametoindex(send_iface.c_str());
      sockaddr.sll_hatype = 1;

      raw_protocol_t::socket d_socket10(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW));   /* Needs root or cap_net_raw permissions */   

      d_socket10.bind(raw_endpoint_t(&sockaddr, sizeof(sockaddr)));
/* End 10G management connection */

/* This currently does not work for unknown reason. Transmitted packet does NOT match buffer contents expected. But the streambuf seems to work.      */

      std::vector<boost::asio::const_buffer> transmitbuffer2;        
      transmitbuffer2.clear();
      transmitbuffer2.push_back(boost::asio::buffer((const void *)srcMAC, sizeof(srcMAC)));
      transmitbuffer2.push_back(boost::asio::buffer((const void *)dstMAC, sizeof(dstMAC)));
      transmitbuffer2.push_back(boost::asio::buffer((const void *)custom_type, sizeof(custom_type)));

      d_socket10.send(boost::asio::buffer(transmitbuffer2));

/* for testing */
    boost::asio::streambuf buffer;
    std::ostream stream( &buffer );    
    unsigned char const deadbeef[] = { 0xde, 0xad, 0xbe, 0xef }; // can't handle 0x00

    stream << "Hello, World!!!"
           << reinterpret_cast< char const * >( deadbeef ); 
    d_socket10.send(buffer.data());    

    } // Close constructor

.
.
.
    udp_sink_impl::work(int noutput_items,
    gr_vector_const_void_star &input_items,
    gr_vector_void_star &output_items)
{
.
.
.
    udpsocket->send_to(transmitbuffer,d_endpoint);

最后,在udp_sink_impl::work函数中,我想替换现有的UDP调用:

代码语言:javascript
复制
udpsocket->send_to(transmitbuffer,d_endpoint); 

使用类似这样的东西:

代码语言:javascript
复制
d_socket10->send(transmitbuffer);

目前,当我这样做时,没有数据包被发送,似乎崩溃或退出程序,而不是连续发送数据,所以我认为这是某种类型的崩溃。

有人能给我解释一下如何在C++中为UDP Sink/Source块实现简单堆栈溢出的指针示例或日本标记化的原始套接字示例吗?Sink (发送)当前是我优先于Source (接收)的优先级。

非常提前谢谢你。任何帮助或建议都是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2017-09-20 01:45:18

在scatter-gather io上的boost doc中,我认为send的语法应该是:

代码语言:javascript
复制
d_socket10.send(transmitbuffer2); // don't add the extra boost::asio::buffer()

我找不到任何使用缓冲区向量的boost::asio::buffer的例子,所以我不确定到底发生了什么(可能有一些我看不到的隐式转换)。

对于流测试,当您使用write成员函数而不是operator<<在流中插入时,必须手动指定大小。类似于:

代码语言:javascript
复制
unsigned char const deadbeef[5] = { 0x00, 0xde, 0xad, 0xbe, 0xef };
stream.write(reinterpret_cast<const char*>(&deadbeef[0]), 5);

这样,您就可以处理发送空字符。

你能展示一下transmitbuffer是如何构建的吗?它是否与transmitbuffer2相同

编辑

段错误表明您试图以非法的方式访问内存。仅从您的代码片段进行调试有些困难,但我会首先检查您发送的缓冲区是否仍然有效。boost::asio::buffer不会复制底层内存,当您准备发送时,它需要保持有效。

您还会在代码片段中混合使用指针和对象,因此请确保没有任何悬空指针,并且在调用send之前,每个人都处于有效状态

编辑2

在头文件中,声明一个名为d_socket10的成员指针,该成员指针从不在构造函数中分配或创建。第147行上的此调用:

代码语言:javascript
复制
raw_protocol_t::socket d_socket10(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW));

创建一个与成员指针同名的对象,当您退出构造函数的作用域时,该对象将被销毁。稍后,您使用未分配任何内容的成员指针调用send,因此出现了segfault。

要修复它,您需要创建它并以与udpsocket相同的方式管理它的生命周期

代码语言:javascript
复制
d_socket10 = new raw_protocol_t::socket(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW));

并在不再需要delete时调用它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46290909

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档