2012-05-06 20 views
9

Estaba pensando en hacer uso de Boost Asio para leer datos de Socket CAN. No hay nada lujoso en linux/can.h, y el dispositivo debe comportarse como la interfaz de bucle invertido , y debe usarse con un conector RAW.boost :: asio over SocketCAN

En cuanto a la interfaz basic_raw_socket parece que puedo hacer uso de basic_raw_socket::assign para asignar la toma nativa creada con

socket(PF_CAN, SOCK_RAW, CAN_RAW); 

Esto es lo que tengo hasta ahora

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

y esto es cómo lo uso en mi aplicación

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

Lo que no entiendo es ¿cómo puedo binds para el punto final local? No hay IPs ni puertos involucrados.

¿Hay algo más que debería implementarse además del punto final para que funcione?

Respuesta

3

La solución es usar posix::stream_descriptor.

Simplemente abra el socket nativo, enlace y luego use posix::basic_stream_descriptor::assign.

+0

¿Podrían presentar el ejemplo completo de lectura/escritura puede marcos al igual que lo hice para Python: http: //libbits.wordpress .com/2012/05/22/socketcan-support-in-python/Yo luego lo ubicaría en http://elinux.org/CAN_Bus#SocketCAN_Support_in_Programming_Languages.2FEnvironments – yegorich

4

aquí es ejemplo de trabajo que he montado con ayuda de este hilo

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

} 
Cuestiones relacionadas