賈小文,賀秀良
(軍事交通學(xué)院 基礎(chǔ)部,天津300161)
串行通信是計(jì)算機(jī)與外圍設(shè)備進(jìn)行數(shù)據(jù)通信常見(jiàn)的通信方式。按電氣標(biāo)準(zhǔn)和協(xié)議串行通信標(biāo)準(zhǔn) 有 RS232-C、RS422、RS485、USB 等[1-2]。RS232-C(ANSI/EIA232 標(biāo)準(zhǔn))是IBM-PC 及其兼容機(jī)上的串行連接標(biāo)準(zhǔn)。由于個(gè)人計(jì)算機(jī)的普及,RS232-C 成為使用最為廣泛的串口通信標(biāo)準(zhǔn)。通用串行總線(universal serial bus,USB)是一個(gè)新的外部總線標(biāo)準(zhǔn),于20 世紀(jì)90 年代由英特爾、康柏、IBM、微軟等多家公司聯(lián)合推出,由于支持熱插拔、即插即用、傳輸速率高等原因,目前被計(jì)算機(jī)廣泛用為與外設(shè)進(jìn)行串行通信的標(biāo)準(zhǔn)接口[3]。筆記本計(jì)算機(jī)由于其輕薄的特點(diǎn),絕大多數(shù)并不提供RS232-C 串口,也即普通意義上的“COM”串口,但都提供USB 接口。當(dāng)筆記本計(jì)算機(jī)與僅支持RS232 串口的設(shè)備進(jìn)行串行通信時(shí),通常需要從USB 到RS232 的轉(zhuǎn)換。這種轉(zhuǎn)換可以通過(guò)專用的芯片完成,比較成熟的芯片有PL2303、CP2102 等[4-5]。通過(guò)USB—RS232 轉(zhuǎn)換,可以方便地利用筆記本對(duì)支持串口通信的設(shè)備進(jìn)行讀寫(xiě)操作。
CSerialPort 類是為了方便對(duì)RS232 串口操作而開(kāi)發(fā)的一個(gè)C + +類,可以代替常用的ActiveX控件進(jìn)行串口應(yīng)用開(kāi)發(fā)。該類封裝了相關(guān)的文件操作Windows API 函數(shù),采用異步文件讀寫(xiě)模型,結(jié)構(gòu)良好,功能明確,能夠滿足絕大多數(shù)串口開(kāi)發(fā)應(yīng)用場(chǎng)合[6]。但是,由于串口應(yīng)用環(huán)境的復(fù)雜性,CSerialPort 類存在一些漏洞,特別是在進(jìn)行USB—RS232 串口讀寫(xiě)操作時(shí),不能向串口寫(xiě)入數(shù)據(jù)。本文分析了這些漏洞產(chǎn)生的原因,并給出了修正漏洞的方案。
在Windows 環(huán)境下,開(kāi)發(fā)RS232 串口經(jīng)常采用的方法是使用ActiveX 控件或者直接采用Windows API 函數(shù)。
當(dāng)采用ActiveX 控件時(shí),通常使用的是微軟開(kāi)發(fā)的MSComm 控件。MSComm 控件屬于微軟組件對(duì)象模型(component object model,COM)的產(chǎn)品,為應(yīng)用程序提供了串行接口收發(fā)數(shù)據(jù)的簡(jiǎn)便方法。
MSComm 采用事件驅(qū)動(dòng)方式和查詢方式,提供了一系列標(biāo)準(zhǔn)通信命令和接口,可以方便地與串口建立連接并對(duì)串口發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。MSComm 與開(kāi)發(fā)環(huán)境無(wú)關(guān),無(wú)論是VC、VB,還是Dephi 等流行開(kāi)發(fā)工具都能使用。MSComm 的缺點(diǎn)是可定制性不強(qiáng),對(duì)于復(fù)雜的串口應(yīng)用場(chǎng)合缺乏靈活性。MSComm 屬于ActiveX 控件,必須注冊(cè)以后才能使用,增加了程序的體積,給使用上帶來(lái)不便。當(dāng)MSComm 不能滿足使用要求時(shí),就必須利用Windows API 直接進(jìn)行串口操作。
利用Windows API 對(duì)串口讀寫(xiě)操作的困難在于異步文件讀寫(xiě)的復(fù)雜性,要寫(xiě)出高效穩(wěn)定的串口讀寫(xiě)程序需要相當(dāng)?shù)木幊讨R(shí)和技巧。這實(shí)際上限制了利用API 直接操作串口的可行性。
CSerialPort 本質(zhì)上屬于利用Windows API 對(duì)串口進(jìn)行操作這種形式。但它以類的形式將相關(guān)Win32 API 以及對(duì)串口文件異步操作所涉及到的多線程、線程同步等復(fù)雜編程技術(shù)封裝起來(lái),大大降低了對(duì)串口讀寫(xiě)操作的復(fù)雜性,提供給使用者比MSComm 更簡(jiǎn)單和直接的使用接口。與MSComm 控件COM 訪問(wèn)方式相比較,CSerialPort不涉及對(duì)讀寫(xiě)數(shù)據(jù)的封裝和轉(zhuǎn)換。CSerialPort 以C + +代碼類的方式提供,可以直接包含到程序源代碼里,不像MSComm 必須安裝注冊(cè)控件才能使用。CSerialPort 結(jié)構(gòu)良好,對(duì)串口的操作采用典型成熟的多線程異步Overlapped 文件讀寫(xiě)模型,所有的源代碼都是公開(kāi)透明的,使用者可以通過(guò)修改或者直接從該類派生而擴(kuò)展該類的功能,寫(xiě)出功能更強(qiáng)的串口操作應(yīng)用程序。同時(shí)該類也是一份很好的關(guān)于串口讀寫(xiě)操作Win32 API 編程的技術(shù)范例,對(duì)于開(kāi)發(fā)自己個(gè)性化的串口讀寫(xiě)應(yīng)用具有一定參考價(jià)值[2]。
CSerialPort 屬于事件驅(qū)動(dòng),使用非常簡(jiǎn)單,讀寫(xiě)串口前先產(chǎn)生該類的實(shí)例,1 個(gè)串口對(duì)應(yīng)1 個(gè)實(shí)例。主程序通過(guò)直接調(diào)用實(shí)例的寫(xiě)操作接口和關(guān)閉接口進(jìn)行寫(xiě)操作和關(guān)閉操作,通過(guò)響應(yīng)消息的方式進(jìn)行讀操作。串口檢測(cè)到的其他事件也以消息的方式發(fā)送給主程序,主程序通過(guò)響應(yīng)該消息來(lái)處理相應(yīng)的串口事件。表1 為CSerialPort 定義的基本消息,表2 為CSerialPort 提供的接口函數(shù)。關(guān)于該類的詳細(xì)使用方法可參考文獻(xiàn)[7]。
表1 CSerialPort 消息
表2 CSerialPort 主要接口函數(shù)(不含返回類型和函數(shù)參數(shù))
CSerialPort 最初發(fā)布只是解決了串口讀寫(xiě)操作最關(guān)鍵的部分,亦即多線程異步overlapped 文件讀寫(xiě)機(jī)制實(shí)現(xiàn),并未充分考慮串口操作所涉及到的一些細(xì)節(jié)問(wèn)題,而是把這些問(wèn)題留給了使用者。使用者可以利用其開(kāi)源特性,根據(jù)自己的應(yīng)用需求直接對(duì)源類進(jìn)行擴(kuò)充和修改,實(shí)現(xiàn)自己要求的功能。這些細(xì)節(jié)問(wèn)題,如果在使用的過(guò)程中不注意,就會(huì)成為程序的漏洞,嚴(yán)重者會(huì)導(dǎo)致串口操作失敗。
CSerialPort 提供寫(xiě)操作接口如下:
當(dāng)要向串口寫(xiě)入數(shù)據(jù)時(shí),CSerialPort 將寫(xiě)操作事件m_hWriteEvent 置為有信號(hào)狀態(tài),同時(shí)將待寫(xiě)入字符串拷貝到寫(xiě)入緩沖區(qū)m_szWriteBuffer,并指定寫(xiě)入字符長(zhǎng)度m_nWriteSize。由于寫(xiě)事件為有信號(hào)狀態(tài),監(jiān)聽(tīng)線程通過(guò)查詢?cè)撔盘?hào)狀態(tài)調(diào)用Windows API 函數(shù)WriteFile 將數(shù)據(jù)寫(xiě)入串口。上述寫(xiě)操作函數(shù)在寫(xiě)入二進(jìn)制數(shù)據(jù)時(shí)存在問(wèn)題。
strcpy 和strlen 函數(shù)都是以標(biāo)準(zhǔn)C/C + +字符串作為操作對(duì)象。在C/C + + 規(guī)范中,標(biāo)準(zhǔn)字符串是以“ 宿州市| 宿迁市| 宜川县| 福建省| 泌阳县| 长汀县| 长治县| 昭通市| 珲春市| 定州市| 武山县| 泗洪县| 酒泉市| 新绛县| 嘉禾县| 昭平县| 革吉县| 定兴县| 安庆市| 遂宁市| 永寿县| 施甸县| 千阳县| 雅江县| 白朗县| 志丹县| 甘泉县| 罗甸县| 唐河县| 舞钢市| 阿尔山市| 济宁市| 包头市| 西林县| 原阳县| 大兴区| 陆丰市| 房山区| 沈阳市| 菏泽市| 凌云县|