[英]boost::asio over SocketCAN
我正在考慮利用Boost Asio從Socket CAN讀取數據。 在linux / can.h中沒有任何花哨的東西,設備應該像loopback接口一樣,並與原始套接字一起使用。
看看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) );
我不太了解的是如何將 s
綁定到本地端點? 沒有涉及IP或端口。
除了端點之外還有其他任何東西可以實現嗎?
這是一個工作示例,在此線程的幫助下組裝
#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();
}
解決方案是使用posix::stream_descriptor
。
只需打開本機套接字,綁定然后使用posix::basic_stream_descriptor::assign
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.