2012-05-06 48 views
9

Tôi đã nghĩ đến việc sử dụng Boost Asio để đọc dữ liệu từ Socket CAN. Không có gì lạ mắt xảy ra trong linux/can.h và thiết bị phải hoạt động giống như giao diện vòng lặp và được sử dụng với ổ cắm thô.boost :: asio over SocketCAN

Nhìn vào giao diện basic_raw_socket vẻ như là tôi có thể tận dụng basic_raw_socket::assign gán các ổ cắm nguồn gốc tạo ra với

socket(PF_CAN, SOCK_RAW, CAN_RAW); 

Đây là những gì tôi có cho đến nay

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

Và đây là cách tôi sử dụng nó trong đơn đăng ký của tôi

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

Những gì tôi không nhận được là làm thế nào để tôi binds đến điểm cuối cục bộ? Không có IP hoặc cổng liên quan.

Có điều gì khác cần được triển khai bên cạnh điểm cuối để làm cho nó hoạt động không?

Trả lời

3

Giải pháp là sử dụng posix::stream_descriptor.

Chỉ cần mở ổ cắm gốc, liên kết và sau đó sử dụng posix::basic_stream_descriptor::assign.

+0

Ông có thể vui lòng cung cấp các ví dụ hoàn chỉnh cho việc đọc/ghi CAN khung giống như tôi đã làm cho nó cho Python: http: //libbits.wordpress .com/2012/05/22/socketcan-support-in-python/Tôi sẽ đặt nó trên http://elinux.org/CAN_Bus#SocketCAN_Support_in_Programming_Languages.2FEnvironments – yegorich

4

Dưới đây là ví dụ làm việc tôi đã lắp ráp với sự giúp đỡ của chủ đề này

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

} 
Các vấn đề liên quan