發布日期:2022-07-15 點擊率:24
隨著網絡嵌入式系統應用的普及,嵌入式系統之間的通信成為工程師關注的焦點之一。除了API或HTTP協議等傳統方式外,電子郵件也可以用來進行數據通信,本文描述了一個用于接收信息的小型SMTP服務器以及發送回函的客戶程序來說明電子郵件通信方式的應用。
通過電子郵件來與網絡嵌入式系統通信有如下優點:(1) 用戶接口是日常使用的標準電子郵件客戶程序,對技術要求較低;(2) 有現成的協議用于從各種設備(桌面電腦、手持設備及網絡電話)發送電子郵件并在因特網上傳輸;(3) 只需稍加處理,便可對嵌入式設備上回復的電子郵件以HTML格式進行編碼,使數據的表現形式更為豐富和易讀;(4) 電子郵件客戶程序有自己的存檔日志,便于進行數據歸檔備份。
郵件系統的組成
在用因特網發送郵件時,我們使用郵件用戶代理(MUA)與本地的郵件傳輸代理(MTA)進行通信,后者則將電子郵件傳送給目標MTA。目標MTA通過一個本地投遞服務器(如POP3)將電子郵件傳送給接收MUA,如圖1所示。
客戶與MTA間傳送電子郵件的協議稱為簡單郵件傳輸協議(SMTP),它的具體條款可在RFC-821中找到。目的MTA接收到郵件,該郵件暫存在接收系統上,郵件接收者可通過POP3將之收集下來(郵局協議)。通過郵局協議可避免在每個需要接收郵件的節點上建立一個SMTP服務器。
協議會話示例
SMTP是一種其于ASCII的簡單協議,可通過標準的遠程登錄客戶程序執行。MTA寄存在端口25上,程序1是一段與稱為Sendmail(紅色顯示部分為用戶輸入)標準MTA的互動會話示例。
通過遠程登錄打開一個Socket會話后,先通過HELO指令表明身份,然后再通過MMAIL FROM指令告知MTA郵件從何而來,并通過RCPT TO指令表明郵件去向何處。最后,發出DATA指令指示MTA以下文本內容是電子郵件的正文。在正文中輸入內容后,通過一個簡單的“.”來結束郵件,這個符號獨占一行。這時MTA便準備將電子郵件發送給指定姓名的接收者。
這個示例所用功能極少,但作為例子已經足夠了。它表明MTA只是一個特殊的命令解釋器。當所有的命令都向MTA發出后,會返回一個數字響應代碼,以便知道是否執行成功。此外還有多種協議了采用這種模式,包括POP3和網絡新聞傳輸協議(NNTP)。
簡單SMTP服務器和客戶實現
以下是一個適用于嵌入式系統的簡單實現。這個實現的目的是在SMTP傳輸系統中開發一個命令-響應協議。服務器接收一個電子郵件,然后對它進行語法分析,找出其中的指令(這種情況下,這個指令位于電子郵件的標題欄中)。如果指令合法,就調用一個處理程序產生電子郵件的響應,該響應傳送到客戶實現上,然后傳輸回去給用戶。整個系統如圖2所示。
嵌入式SMTP服務器的組件和客戶與圖1所示的傳統圖形有所不同。客戶MUA配置了一個SMTP網關(發出郵件服務器)作為嵌入式器件的地址(由于服務器既充當MTU又充當自動MUA)。嵌入式客戶采用SMTP GATEWAY #define(程序1)來定義從何處發送響應電子郵件。
實現過程
主要功能(可從獲得完整的源代碼)提供了基本的服務器插座設置以便郵件連接。將插座綁定到端口25,即SMTP服務的標準端口。然后執行一個循環等待連接,當有客戶連接時調用MailReceive函數。為了簡化實現,一次只處理一個連接。
MailReceive函數實現SMTP協議的服務器端功能,如實例程序2所示。MailReceive函數中的第一步是將初始化標志發送給客戶程序,然后等待其響應。接著順序等待接收“MAIL
FROM”、“RCPT TO”及“DATA”命令,并存儲結果及發送相應的返回碼。
接收郵件正文的操作十分簡單,只需將收到的字符緩存起來,直到接收到一個特殊的字符序列為止。客戶程序發送“
這時存放郵件內容的字符串數組中已接收到整個郵件原文。然后調用mailParse函數分析該數組,找出相關指令。
程序2中給出了mailParse函數的實現。該函數首先檢索“Subject:”字符串,如果找到則存儲相應的標題內容。然后將標題串與目標所支持的命令(PING、SENSOR和RESET)相比較,并調用相應的處理函數。
實例代碼中每個處理函數都包含了相同的基本處理過程。首先分配一個郵件標題結構,根據希望提供的響應填入該結構的相關字段,然后調用mailSend函數發送郵件(參見示例程序3)。sendResponse 和processCommand函數的功能十分顯而易見。
函數sendSensorData略有不同,它發送的是HTML格式的文本。除了郵件正文不同外,其內容類型標志也不同:普通正文的內容標志為“text/plain”,而HTML格式的內容標志為“text/html”,表示郵件中可能包含HTML標記。這些處理程序十分簡單,但可以進行擴展以支持任何電子郵件客戶程序所允許的嵌入標記(包括圖象、聲音等數據的傳輸)。
MailSend函數實現SMTP客戶端的協議處理。這基本上是服務器端代碼的反向處理。
另外值得注意的是客戶報頭文件,它定義了mailHeader結構(見實例程序1)。該結構中多數的字段都一目了然,其中一個特殊的字段是specialHeaders。如果電子郵件客戶程序把郵件中所有的標題域都顯示出來,將發現許多不常見的內容,多數都可在IETF的“通用互連網消息標題”(RFC-2076)文檔中找到。通過specialHeaders字段可調整電子郵件的處理。例如可采用“Priority: Urgent”標題注明郵件的重要性,或采用“Content-MD5:”標題(以及相應的校驗碼)來保證在傳遞過程中郵件的內容未發生改變。
測試設置
實例代碼可在Linux上直接編譯并運行。編譯前必須先配置兩個參數程序才能正常運行(在client.h文件中)。
第一個參數是SMTP GATEWAY宏定義,它設定嵌入式SMTP客戶程序發送電子郵件的目標,一般是用戶有發送或接收帳號的SMTP網關,或者是提供電子郵件中轉服務的網關。該參數可設為一個IP地址或一個域名(mailSend函數中的代碼具備域名解析功能)。
第二個可配置的參數是SOURCE_E-MAIL_ADDRESS,該參數并不十分關鍵,它表示回復郵件中“From:”字段的內容(即發送方的標志)。這些參數設置好以后,只需簡單地“Make”就可生成“Tinyms”可執行程序鏡像。
發出郵件的電子郵件桌面程序必須將其SMTP網關(或發送服務器)配置為嵌入式設備的IP地址。當用軟件發送電子郵件時,無論接收方在哪里,郵件都要首先經過預先設好的SMTP網關(即嵌入式設備)。嵌入式設備并不關心地址,它只是處理所有收到的郵件,并把回復內容傳給發送方。注意標題域(Subject:)的內容是要執行的命令(如SENSOR或者PING)。在列舉的實現中忽略了郵件的正文,但只需稍加修改舊可對正文進行處理,因為整個郵件的原文都存放在字符數組中。
本文小結
現在可以向嵌入式設備發送電子郵件并獲得響應了,但這只是一個最基本的配置,它給傳統的通信模式提供了一種有趣的替代。我們可對這一實現進行多種擴展,例如支持在電子郵件正文中嵌入XML消息(通過某種XML分析器);還可通過在接收或發送的郵件中附加Base64或“Quoted-Printable MIME”編碼/解碼處理功能來支持二進制附件。利用后者可提供向嵌入式設備發送軟件更新或接收采集的二進制數據的功能(在傳統的圖像等多媒體數據之外)。最后,不用任何額外的改變,就可由嵌入式設備在異常情況下發送電子郵件報警。
作者簡介:
M. Tim Jones是Emulex公司的軟件工程師。他從1986年到現在一直從事嵌入式軟件開發,其范圍十分廣泛,從航空設備的操作系統內核到地面嵌入式網絡,無所不及。Tim獲得了計算機科學的學士和碩士學位。可通過mtj@與他聯系。
作者:M. Tim Jones
Emulex公司