提高:: ASIO超过SocketCAN(boost::asio over SocketCAN)

2019-07-29 06:58发布

我想利用的升压短耳从读取数据的Socket CAN 。 有没有什么特别的事情是LINUX / can.h对应 ,而且该设备会表现得像loopback接口,并配有原始套接字使用。

纵观basic_raw_socket看来我可以利用的接口basic_raw_socket ::分配到与分配产生与天然插座

socket( PF_CAN, SOCK_RAW, CAN_RAW );

这是我到目前为止

namespace can {
       class CanSocket {
       public:
               typedef boost::asio::ip::basic_endpoint<CanSocket> endpoint;
               typedef boost::asio::ip::basic_resolver_query<CanSocket> resolver_query;
               typedef boost::asio::ip::basic_resolver_iterator<CanSocket> resolver_iterator;
               typedef boost::asio::basic_raw_socket<CanSocket> socket;
               typedef boost::asio::ip::basic_resolver<CanSocket> resolver;

               CanSocket()
                       : _protocol( CAN_RAW )
                       , _family( PF_CAN )
               {
               }

               static CanSocket v4()
               {
                       return CanSocket();
               }
               static CanSocket v6();
               int type() const;
               int protocol() const;
               int family() const;

               friend bool operator==(const CanSocket& p1, const CanSocket& p2)
               {
                       return p1._protocol != p2._protocol || p1._family != p2._family;
               }
               friend bool operator!=(const CanSocket& p1, const CanSocket& p2)
               {
                       return p1._protocol == p2._protocol || p1._family == p2._family;
               }

       private:
               int _protocol;
               int _family;
};
}

这是我如何使用它在我的应用

   boost::asio::io_service ioserv;

   CanSocket::socket s( ioserv );

   int sock = socket( PF_CAN, SOCK_RAW, CAN_RAW );

   s.assign(CanSocket::v4(), sock);

   struct ifreq ifr;
   strcpy(ifr.ifr_name, "vcan0");
   ioctl(sock, SIOCGIFINDEX, &ifr); /* ifr.ifr_ifindex gets filled
                                 * with that device's index */

   /* Select that CAN interface, and bind the socket to it. */

   /* this should be the endpoint */
   struct sockaddr_can addr;
   addr.can_family = AF_CAN;
   addr.can_ifindex = ifr.ifr_ifindex;

   /* s.bind (....) */
   bind( sock, (struct sockaddr*)&addr, sizeof(addr) );

我不太得到的是我怎么绑定 s到本地端点? 有没有涉及到IP地址或端口。

还有什么应该除了端点得到它去实施?

Answer 1:

这里是工作示例,组装该线程的帮助

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <iostream>

#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <linux/can.h>
#include <linux/can/raw.h>

#include <boost/asio.hpp>
#include <boost/bind.hpp>

void data_send(void) {
  std::cout << "omg sent" << std::endl;
}

void data_rec(struct can_frame &rec_frame,
              boost::asio::posix::basic_stream_descriptor<> &stream) {
  std::cout << std::hex << rec_frame.can_id << "  ";
  for (int i = 0; i < rec_frame.can_dlc; i++) {
    std::cout << std::hex << int(rec_frame.data[i]) << " ";
  }
  std::cout << std::dec << std::endl;
  stream.async_read_some(
      boost::asio::buffer(&rec_frame, sizeof(rec_frame)),
      boost::bind(data_rec, boost::ref(rec_frame), boost::ref(stream)));
}

int main(void) {
  struct sockaddr_can addr;
  struct can_frame frame;
  struct can_frame rec_frame;
  struct ifreq ifr;

  int natsock = socket(PF_CAN, SOCK_RAW, CAN_RAW);

  strcpy(ifr.ifr_name, "vcan0");
  ioctl(natsock, SIOCGIFINDEX, &ifr);

  addr.can_family = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;
  if (bind(natsock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror("Error in socket bind");
    return -2;
  }

  frame.can_id = 0x123;
  frame.can_dlc = 2;
  frame.data[0] = 0x11;
  frame.data[1] = 0x23;

  boost::asio::io_service ios;
  boost::asio::posix::basic_stream_descriptor<> stream(ios);
  stream.assign(natsock);

  stream.async_write_some(boost::asio::buffer(&frame, sizeof(frame)),
                          boost::bind(data_send));
  stream.async_read_some(
      boost::asio::buffer(&rec_frame, sizeof(rec_frame)),
      boost::bind(data_rec, boost::ref(rec_frame), boost::ref(stream)));
  ios.run();
}


Answer 2:

该解决方案是使用posix::stream_descriptor

只要打开本地套接字,绑定,然后使用posix::basic_stream_descriptor::assign



文章来源: boost::asio over SocketCAN