CAN编程示例之socket CAN
socket CAN概念
socketcan子系统是在Linux下CAN协议(Controller Area Network)实现的一种实现方法。 CAN是一种在世界范围内广泛用于自动控制、嵌入式设备和汽车领域的网络技术。Linux下最早使用CAN的方法是基于字符设备来实现的,与之不同的是Socket CAN使用伯克利的socket接口和linux网络协议栈,这种方法使得can设备驱动可以通过网络接口来调用。Socket CAN的接口被设计的尽量接近TCP/IP的协议,让那些熟悉网络编程的程序员能够比较容易的学习和使用。
socket CAN的应用
在Socket CAN之前Linux中已经有了一些CAN的实现方法,那为什么还要启动Socket CAN这个项目呢?大多数已经存在的实现方法仅仅作为某个具体硬件的设备驱动,它们往往基于字符设备并且提供的功能很少。那些方案通常是由一个针对具体硬件的设备驱动提供的字符设备接口来实现原始can帧的发送和接收,并且直接和控制器硬件打交道。帧队列和ISO-TP这样的高层协议必须在用户空间来实现。就像串口设备接口一样,大多数基于字符设备的实现在同一时刻仅仅支持一个进程的访问。如果更换了CAN控制器,那么同时也要更换另一个设备驱动,并且需要大多数应用程序重新调整以适应新驱动的API。
Socket CAN被设计用来克服以上种种不足。这种新的协议族实现了用户空间的socket接口,它构建于Linux网络层之上,因此可以直接使用已有的队列功能。CAN控制器的设备驱动将自己作为一个网络设备注册进Linux的网络层,CAN控制器收到的CAN帧可以传输给高层的网络协议和CAN协议族,反之,发送的帧也会通过高层给CAN控制器。传输协议模块可以使用协议族提供的接口注册自己,所以可以动态的加载和卸载多个传输协议。事实上,CAN核心模块不提供任何协议,也不能在没有加载其它协议的情况下单独使用。同一时间可以在相同或者不同的协议上打开多个套接字,可以在相同或者不同的CAN ID上同时监听和发送(listen/send)。几个同时监听具有相同ID帧的套接字可以在匹配的帧到来后接收到相同的内容。如果一个应用程序希望使用一个特殊的协议(比如ISO-TP)进行通信,只要在打开套接字的时候选择那个协议就可以了,接下来就可以读取和写入应用数据流了,根本无需关心CAN-ID和帧的结构等信息。
socket CAN通信过程
socket通信模型如下图:
(一)在服务端建立一个ServerSocket,绑定相应的端口,并且在指定的端口进行侦听,等待客户端的连接。
(二)当客户端创建连接Socket并且向服务端发送请求。
(三)服务器收到请求,并且接受客户端的请求信息。一旦接收到客户端的连接请求后,会创建一个链接socket,用来与客户端的socket进行通信。 通过相应的输入/输出流进行数据的交换,数据的发送接收以及数据的响应等等。
(四)当客户端和服务端通信完毕后,需要分别关闭socket,结束通信。
socket通信实现步骤:
了解Socket通信模型后,就可以简化出Socket通信的实现步骤:
(一)创建ServerSocket和Socket。
(二)打开链接到Socket的输入/输出流。
(三)按照协议对Socket进行读/写操作。
(四)关闭输入输出流、关闭Socket。
如何使用socket CAN
就像TCP/IP协议一样,在使用CAN网络之前你首先需要打开一个套接字。CAN的套接字使用到了一个新的协议族,所以在调用socket(2)这个系统函数的时候需要将PF_CAN作为第一个参数。当前有两个CAN的协议可以选择,一个是原始套接字协议( raw socket protocol),另一个是广播管理协议BCM(broadcast manager)。你可以这样来打开一个套接字:
在成功创建一个套接字之后,你通常需要使用bind(2)函数将套接字绑定在某个CAN接口上。在绑定 (CAN_RAW)或连接(CAN_BCM)套接字之后,你可以在套接字上使用read(2)/write(2),也可以使用send(2)/sendto(2)/sendmsg(2)和对应的recv*操作。当然也会有CAN特有的套接字选项。