socket CAN概念
socketcan子系統(tǒng)是在Linux下CAN協(xié)議(Controller Area Network)實(shí)現(xiàn)的一種實(shí)現(xiàn)方法。 CAN是一種在世界范圍內(nèi)廣泛用于自動(dòng)控制、嵌入式設(shè)備和汽車領(lǐng)域的網(wǎng)絡(luò)技術(shù)。Linux下最早使用CAN的方法是基于字符設(shè)備來(lái)實(shí)現(xiàn)的,與之不同的是Socket CAN使用伯克利的socket接口和linux網(wǎng)絡(luò)協(xié)議棧,這種方法使得can設(shè)備驅(qū)動(dòng)可以通過(guò)網(wǎng)絡(luò)接口來(lái)調(diào)用。Socket CAN的接口被設(shè)計(jì)的盡量接近TCP/IP的協(xié)議,讓那些熟悉網(wǎng)絡(luò)編程的程序員能夠比較容易的學(xué)習(xí)和使用。
socket CAN的應(yīng)用
在Socket CAN之前Linux中已經(jīng)有了一些CAN的實(shí)現(xiàn)方法,那為什么還要啟動(dòng)Socket CAN這個(gè)項(xiàng)目呢?大多數(shù)已經(jīng)存在的實(shí)現(xiàn)方法僅僅作為某個(gè)具體硬件的設(shè)備驅(qū)動(dòng),它們往往基于字符設(shè)備并且提供的功能很少。那些方案通常是由一個(gè)針對(duì)具體硬件的設(shè)備驅(qū)動(dòng)提供的字符設(shè)備接口來(lái)實(shí)現(xiàn)原始can幀的發(fā)送和接收,并且直接和控制器硬件打交道。幀隊(duì)列和ISO-TP這樣的高層協(xié)議必須在用戶空間來(lái)實(shí)現(xiàn)。就像串口設(shè)備接口一樣,大多數(shù)基于字符設(shè)備的實(shí)現(xiàn)在同一時(shí)刻僅僅支持一個(gè)進(jìn)程的訪問(wèn)。如果更換了CAN控制器,那么同時(shí)也要更換另一個(gè)設(shè)備驅(qū)動(dòng),并且需要大多數(shù)應(yīng)用程序重新調(diào)整以適應(yīng)新驅(qū)動(dòng)的API。
Socket CAN被設(shè)計(jì)用來(lái)克服以上種種不足。這種新的協(xié)議族實(shí)現(xiàn)了用戶空間的socket接口,它構(gòu)建于Linux網(wǎng)絡(luò)層之上,因此可以直接使用已有的隊(duì)列功能。CAN控制器的設(shè)備驅(qū)動(dòng)將自己作為一個(gè)網(wǎng)絡(luò)設(shè)備注冊(cè)進(jìn)Linux的網(wǎng)絡(luò)層,CAN控制器收到的CAN幀可以傳輸給高層的網(wǎng)絡(luò)協(xié)議和CAN協(xié)議族,反之,發(fā)送的幀也會(huì)通過(guò)高層給CAN控制器。傳輸協(xié)議模塊可以使用協(xié)議族提供的接口注冊(cè)自己,所以可以動(dòng)態(tài)的加載和卸載多個(gè)傳輸協(xié)議。事實(shí)上,CAN核心模塊不提供任何協(xié)議,也不能在沒(méi)有加載其它協(xié)議的情況下單獨(dú)使用。同一時(shí)間可以在相同或者不同的協(xié)議上打開(kāi)多個(gè)套接字,可以在相同或者不同的CAN ID上同時(shí)監(jiān)聽(tīng)和發(fā)送(listen/send)。幾個(gè)同時(shí)監(jiān)聽(tīng)具有相同ID幀的套接字可以在匹配的幀到來(lái)后接收到相同的內(nèi)容。如果一個(gè)應(yīng)用程序希望使用一個(gè)特殊的協(xié)議(比如ISO-TP)進(jìn)行通信,只要在打開(kāi)套接字的時(shí)候選擇那個(gè)協(xié)議就可以了,接下來(lái)就可以讀取和寫入應(yīng)用數(shù)據(jù)流了,根本無(wú)需關(guān)心CAN-ID和幀的結(jié)構(gòu)等信息。
socket CAN通信過(guò)程
socket通信模型如下圖:
(一)在服務(wù)端建立一個(gè)ServerSocket,綁定相應(yīng)的端口,并且在指定的端口進(jìn)行偵聽(tīng),等待客戶端的連接。
(二)當(dāng)客戶端創(chuàng)建連接Socket并且向服務(wù)端發(fā)送請(qǐng)求。
(三)服務(wù)器收到請(qǐng)求,并且接受客戶端的請(qǐng)求信息。一旦接收到客戶端的連接請(qǐng)求后,會(huì)創(chuàng)建一個(gè)鏈接socket,用來(lái)與客戶端的socket進(jìn)行通信。 通過(guò)相應(yīng)的輸入/輸出流進(jìn)行數(shù)據(jù)的交換,數(shù)據(jù)的發(fā)送接收以及數(shù)據(jù)的響應(yīng)等等。
(四)當(dāng)客戶端和服務(wù)端通信完畢后,需要分別關(guān)閉socket,結(jié)束通信。
socket通信實(shí)現(xiàn)步驟:
了解Socket通信模型后,就可以簡(jiǎn)化出Socket通信的實(shí)現(xiàn)步驟:
(一)創(chuàng)建ServerSocket和Socket。
(二)打開(kāi)鏈接到Socket的輸入/輸出流。
(三)按照協(xié)議對(duì)Socket進(jìn)行讀/寫操作。
(四)關(guān)閉輸入輸出流、關(guān)閉Socket。
如何使用socket CAN
就像TCP/IP協(xié)議一樣,在使用CAN網(wǎng)絡(luò)之前你首先需要打開(kāi)一個(gè)套接字。CAN的套接字使用到了一個(gè)新的協(xié)議族,所以在調(diào)用socket(2)這個(gè)系統(tǒng)函數(shù)的時(shí)候需要將PF_CAN作為第一個(gè)參數(shù)。當(dāng)前有兩個(gè)CAN的協(xié)議可以選擇,一個(gè)是原始套接字協(xié)議( raw socket protocol),另一個(gè)是廣播管理協(xié)議BCM(broadcast manager)。你可以這樣來(lái)打開(kāi)一個(gè)套接字:
在成功創(chuàng)建一個(gè)套接字之后,你通常需要使用bind(2)函數(shù)將套接字綁定在某個(gè)CAN接口上。在綁定 (CAN_RAW)或連接(CAN_BCM)套接字之后,你可以在套接字上使用read(2)/write(2),也可以使用send(2)/sendto(2)/sendmsg(2)和對(duì)應(yīng)的recv*操作。當(dāng)然也會(huì)有CAN特有的套接字選項(xiàng)。