2012-05-06 148 views
9

我正在考虑使用Boost Asio来读取Socket CAN的数据。 linux/can.h中没有什么特别的事情发生,设备应该 的行为类似于回送接口,并且与原始套接字一起使用。boost :: asio通过SocketCAN

望着basic_raw_socket界面似乎我可以利用 basic_raw_socket::assign分配与

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

我不太清楚的是我如何binds到本地端点?没有涉及的IP或端口。

除了端点以外还有其他应该实现的功能吗?

回答

3

解决方法是使用posix::stream_descriptor

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

+0

能否请您阅读提供了完整的例子/写CAN帧就像我做了它的Python:HTTP://libbits.wordpress .com/2012/05/22/socketcan-support-in-python /然后我将它放在http://elinux.org/CAN_Bus#SocketCAN_Support_in_Programming_Languages.2FEnvironments – yegorich

4

这里工作例子,我组装了该线程的帮助

/// Encapsulates the flags needed for socket CAN. 
/** 
    * The can class contains flags necessary for CAN sockets. 
    */ 

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

#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) 
{ 
    //int nbytes; 
    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(); 

}