基 於Win95 TAPI 的 調 制 解 調 器 編 程 (轉)
作者:譚 安 平----
一、 簡 介:
---- 隨 著Win95 操 作 系 統 的 普 及, 計 算 機 之 間 的 通 信 已 經 成 為 大 多 數 應 用 程 序 開 發 的 要 求, 這 其 中 的 主 要 原 因 是Win95 不 僅 僅 能 夠 支 持 大 多 數 硬 件, 而 且 為 硬 件 的 操 作 提 供 了 方 便 的 編 程 接 口(),Win95 的 應 用 程 序 接 口(API) 提 供 的 通 信 手 段 大 致 分 為 以 下 幾 類: 1 基 於 協 議 的Winsock API, 可 實 現 局 域 網 上 或 互 聯 網 上 的 微 機 通 信; 2 基 於 進 程 之 間 的 通 信 技 術: 動 態 數 據 交 換( D D E); 3 基 於 直 接 電 纜 連 接 的 通 信 技 術, 可 直 接 操 作 串 行 口、 並 行 口 以 及 遠 紅 外 線 接 口; 4 基 於 電 話 線 路 的 通 信 應 用 程 序 接 口( T A P I/Telephony API), 可 方 便 地 控 制 調 制 解 調 器; 從 目 前 的 發 展 狀 況 看 來, 調 制 解 調 器 已 經 成 為 遠 距 離 通 信 的 一 種 重 要 工 具, 為 此 及 公 司 聯 合 開 發 了TAPI 這 樣 一 個 編 程 接 口, 而 且, 使 用API 函 數 編 制 的 程 序 段 既 適 用 於Borland C++ 編 譯 器, 同 時 也 能 插 入Visual C++ 程 序 中 編 譯 運 行, 作 為Win95 的 應 用 程 序 編 制 人 員, 學 會 使 用TAPI 編 程 操 作 調 制 解 調 器 通 過 電 話 線 路 進 行 通 信 這 一 技 術 是 很 有 必 要 的。 下 面 就TAPI 編 程 進 行 討 論:
二、 通 信 過 程 描 述
---- 1 初 始 化 線 路( 通 信 雙 方 都 應 該 初 始 化 線 路)
---- 通 過 使 用lineInitialize 函 數 初 始 化TAPI.DLL 得 到TAPI 使 用 句 柄 的 指 針hTapi, 請 注 意 參 數 中 回 調 函 數 的 定 義( 所 有 提 及 函 數 的 用 法 均 可 從BC++5.0 及Visual C++5.0 的 幫 助 中 獲 得); 通 過 調 用lineOpen 函 數( 用 到 參 數hTapi) 獲 得 線 路 句 柄hLine; 再 利 用lineGetID( 用 到 參 數hLine) 獲 取 調 制 解 調 器 句 柄hModem
---- 2 配 置 線 路( 可 選)
----
---- 調 用SetCommConfig( 用 到hModem) 改 變 調 制 解 調 器 的 設 置
---- 3 撥 號( 由 呼 叫 方 執 行)
---- 使 用lineMakeCall 函 數( 用 到hLine) 進 行 撥 號, 完 成 後 獲 得 呼 叫 句 柄hCall( 呼 叫 方 的 呼 叫 句 柄)
---- 4 應 答 鏈 接( 由 被 呼 叫 方 執 行)
---- 被 呼 叫 的 一 方 的 回 調 函 數 得 到LINECALLSTATE_OFFERING 消 息 時, 調 用lineAnswer 函 數 實 現 自 動 應 答( 呼 叫 句 柄hCall 由 回 調 函 數 的 參 數 給 出)
---- 5 數 據 通 信( 雙 方)
---- 當 回 調 函 數 收 到LINECALLSTATE_CONNECTED 消 息 後, 請 先 清 除 接 收 緩 衝 區, 可 以 使 用 函 數 為WriteFile 及ReadFile 函 數 進 行 數 據 交 換, 注 意 參 數hFile 為 調 制 解 調 器 句 柄hModem
---- 6 掛 機( 某 一 方)
---- 通 信 完 畢 任 何 一 方 都 可 以 調 用 函 數lineDrop(hCall,NULL,0) 來 停 止 呼 叫, 該 函 數 還 發 送LINECALLSTATE_IDLE 消 息 給 回 調 函 數
---- 7 關 閉 線 路( 雙 方)
---- 通 信 雙 方 的 回 調 函 數 在 收 到LINECALLSTATE_IDLE 消 息 時 都 應 該 調 用 函 數lineDeallocateCall(hCall) 釋 放 相 應 呼 叫 佔 用 的 資 源; 當 回 調 函 數 收 到LINECALLSTATE_DINNECTED 消 息 時 請 使 用lineClose(hLine) 釋 放 由lineOpen 分 配 的 資 源, 調 用lineShutDown(hTapi) 釋 放 為 線 路 設 備 分 配 的 資 源
三、 軟 硬 件 環 境
---- 下 圖 示 意 出 了 我 們 的 應 用 程 序 所 處 的 位 置 以 及 涉 及 到 的 軟 硬 件 環 境:
---- 我 們 的 通 信 應 用 程 序 通 過TAPI 操 作Modem 撥 號、 應 答、 鏈 接、 掛 機 控 制 電 話 呼 叫, 在 編 制D應 用 程 序 的 時 候, 我 們 經 常 使 用Hayes 兼 容 的AT 命 令 集 來 完 成 這 些 操 作, 由 於 各 調 制 解 調 器 廠 家 對 該 命 令 集 都 做 了 各 自 的 擴 展, 因 而, 我 們 的DOS 應 用 程 序 一 般 只 能 操 作 一 小 部 分 調 制 解 調 器, 而 各 廠 家 都 提 供 驅 動 程 序, 所 以, 使 用TAPI 編 制 的 應 用 程 序 能 夠 操 作 絕 大 多 數 調 制 解 調 器; 圖 中 的 通 信API 是 應 用 程 序 發 送、 接 收 數 據 的 編 程 接 口。
四、 程 序 流 程 結 構 框 圖
---- 由 於Win95 為 多 任 務 操 作 系 統, 我 們 的 流 程 圖 只 能 代 表 本 應 用 程 序 的 執 行 先 後 關 系, 程 序 中 的 等 待 及 檢 測 實 際 上 是 等 待Win95 提 供 的 消 息, 所 以 並 不 佔 用 時 間, 在 下 面 的 程 序 中 可 以 看 出。 另 外, 數 據 交 換 的 協 議 可 由 自 己 制 定, 也 可 使 用 已 有 的 協 議。
五、 軟 件 編 制
---- 由 於Windows 編 程 的 框 架 基 本 相 同, 在 此 我 們 只 介 紹 涉 及 到 通 信 的 一 部 分 源 程 序:
---- 1 頭 文 件 中 應 該 包 括:
---- #include
---- 請 注 意 工 程 文 件 的 屬 性 應 該 是Windows 32 位 應 用 程 序
---- 2 通 信 所 涉 及 到 的 一 些 全 局 變 量 定 義 及 類 型 定 義:
char RecBuf[20],buf[20]// 緩 衝 區 D Error; // 錯 誤 碼 COMSTAT Status; // 狀 態 碼 DWORD NumLine; // 允 許 使 用 的 線 路 設 備 數 LINECALLPARAMS para;// 呼 叫 參 數 TmyDecFrame * pwin=NULL;// 主 窗 口 指 針 HLINEAPP myhTapi;// 線 路 應 用 程 序 句 柄 HLINE myhLine;// 線 路 句 柄 HANDLE myhModem;// 調 制 解 調 器 句 柄 HCALL myhCall;// 呼 叫 句 柄 typedef struct tagModemID{ HANDLE hModem; char ModemName[1]; }ModemID;
---- 3 下 面 為 獲 取 調 制 解 調 器 句 柄 的 函 數 定 義
---- 因 為 每 個 調 制 解 調 器 的 標 志 字 符 串 長 度 不 一, 所 以 函 數 中 用 到 了 可 變 長 度 的 字 符 串, 處 理 方 法 是 先 為 字 符 串 指 針 分 配sizeof(VARSTRING) 大 小 的 空 間, 再 利 用 該 空 間 容 納 調 用LineGetID 時Windows 返 回 的 信 息, 根 據 返 回 信 息 判 斷 所 需 空 間 大 小 重 新 分 配 空 間, 再 次 調 用LineGetID 就 可 以 取 得 完 整 的 標 志 字 符 串。
void GethModem(HLINE hLine) { ModemID far *mid; VARSTRING * str; LONG lid; DWORD size; char mark=1; str=(VARSTRING *)malloc(sizeof(VARSTRING)); if(!str) return NULL; str- >dwTotalSize=sizeof(VARSTRING); do { if((lineGetID(myhLine,0,NULL,LINECALL_LINE,str, "comm/datamodem")==0)&&(str- >dwTotalSize ---- 4 在 主 窗 口 初 始 化 函 數 中 加 入 對 線 路 的 初 始 化 過 程: pwin=this;// 獲 得 主 窗 口 指 針 while(lineInitialize(&myhTAPI,GetModule()- >GetInstance(), (LINECALLBACK)MakeProcInstance((FROC) lpfnCallback, GetModule()- >GetInstance()), "TRY",&NumLine )==LINEERR_REINIT) { sleep(1);// 延 遲 }; Error=lineOpen(hTAPI,0,&HLine,0x10004,0,0,LINECALLPRIVILEGE_MONITOR+ LINECALLPRIVILEGE_OWNER,LINEMEDIAMODE_DATAMODEM,NULL); if(Error!=0) { sprintf(buf,"%lx",Error); MessageBox(buf,0,MB_OK); } else { GethModem(myhLine);// 取 得myhModem 的 值 if(myhModem!=NULL) { para.dwBearerMode=LINEBEARERMODE_VOICE; para.dwMediaMode=LINEMEDIAMODE_DATAMODEM; para.dwTotalSize=sizeof(LINECALLPARAMS); Error=lineMakeCall(myhLine,&myhCall,"8880751",0,¶); If(Error!=0) { sprintf(buf,"%lx",Error); MessageBox(buf,0,MB_OK); } } } } ---- 5 呼 叫 方 回 調 函 數 的 定 義 void far pascal TMyDecFrame::lpfnCallback (DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)// 引數定義同lineCallbackFunc中的引數定義 { int Rec_num=0; switch(dwParam1) { case LINECALLSTATE_CONNECTED: DWORD len; ClearCommError(myhModem,&Error,&Status); Rec_num=Status.cbInQue; ReadFile(myhModem,RecBuf,Rec_num,&len,0); //至此已經為資料通訊做好了前期準備,可設立標誌 WriteFile(myhModem,"Success",7,&len,0); ReadFile(myhModem,RecBuf,8,&len,0); pwin->MessageBox(RecBuf,0,MB_OK); break; case LINECALLSTATE_IDLE: lineDeallocateCall(myhCall); break; case LINECALLSTATE_DISCONNECTED: lineClose(myhLine); lineShutDown(myhTapi); break; } } ---- 6 被 叫 方 回 調 函 數 的 定 義 void far pascal TMyDecFrame::lpfnCallback(DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { int Rec_num=0; switch(dwParam3) { case LINECALLPRIVILEGE_OWNER: myhCall=(HCALL)hDevice; Break; }//只有對呼叫具有私有特權的者才能應答呼叫, 在此獲得呼叫控制程式碼 switch(dwParam1) { case LINECALLSTATE_CONNECTED: DWORD len; ClearCommError(myhModem,&Error,&Status); Rec_num=ComS.cbInQue; ReadFile(myhModem,RecBuf,Rec_num,&len,0);// 清 除 接 收 緩 衝 區 ReadFile(myhModem,RecBuf,7,&len,0); WriteFile(myhModem,"Received",8,&len,0); pwin- >MessageBox(RecBuf,0,MB_OK); break; case LINECALLSTE_OFFERING: lineAnswer(myhCall,NULL,0); break;// 完 成 自 動 應 答 case LINECALLSTATE_IDLE: lineDeallocateCall(myhCall); break; case LINECALLSTATE_DISCONNECTED: lineClose(myhLine); lineShutDown(myhTapi); break; } } ---- 以 上 程 序 中 使 用 的 是 同 步 讀 寫 方 式, 只 要WriteFile 或 者ReadFile 沒 有 完 成 指 定 的I/O 任 務, 它 們 就 不 會 返 回 進 程, 在 許 多 情 況 下, 這 是 令 人 難 以 容 忍 的CPU 時 間 浪 費; 改 進 的 辦 法 是 在 每 次 讀 之 前 採 用ClearCommError 函 數 確 定 系 統 的 串 行 口 緩 衝 區 中 到 底 有 了 多 少 字 節 的 接 收 數 據, 而 寫 方 式 採 用 異 步 方 式, 首 先 應 該 定 義 一 個OVERLAPPED 結 構, 從BC++5.0 中 獲 得 的 結 構 定 義 如 下: typedef struct _OVERLAPPED { // o DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent; } OVERLAPPED; ---- 我 們 定 義OVERLAPPED myOVLP; ---- 我 們 只 用 到 了 其 中 的hEvent 成 員, 其 他 成 員 均 置0;hEvent 設 置 為CreateEvent(NULL,TRUE,FALSE,NULL) 產 生 的 事 件 句 柄; 然 後 如 下 調 用WriteFile(myhModem,"Received",8,&len,&myOVLP); ---- 函 數 將 立 即 返 回, 此 後, 只 要GetOverlappedResult 函 數 返 回TRUE, 寫 操 作 就 算 完 成 了。 六、 改 進 措 施
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992601/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 遠端控制調變解調器 (轉)
- 調研:如何基於Linux平臺實現自主設計的排程器Linux
- Golang 的 協程排程機制 與 GOMAXPROCS 效能調優Golang
- 【轉】基於RHEL5的websphere + IHS 6.1調優Web
- win10調變解調器錯誤怎麼辦 win10調變解調器錯誤的解決方法Win10
- 調變解調器已刪除的解決辦法
- 用AT命令除錯調變解調器除錯
- win10如何重啟調變解調器 win10電腦怎麼重置調變解調器Win10
- VC 調 用ACM 音 頻 壓 縮 編 程 接 口 的 方 法 (轉)ACM
- 基於各種感測器的空調系統監控
- TAPI基本函式 (轉)API函式
- win10如何解決調變解調器出現錯誤 寬頻調變解調器連線出現問題Win10
- JVM的垃圾回收機制詳解和調優JVM
- AutoTiKV:基於機器學習的資料庫調優機器學習資料庫
- 資料排程元件:基於Azkaban協調時序任務執行元件
- 基於python + opencv的影片播放調節功能PythonOpenCV
- oracle的調優(轉)Oracle
- 用TAPI 3.0 建立呼叫中心 (轉)API
- Oracle效能最佳化調整--調整重做機制Oracle
- 編碼與調製
- Github基於Web的編輯器GithubWeb
- 通訊原理:基於MATLAB的AM調幅分析Matlab
- 是德科技應用QualcommLTE物聯網調變解調器
- 基於TRIZ理論解決切割機進刀調節難題
- 關於WiFi協議的調製方式詳解WiFi協議
- 【Matlab】BFSK的調製與解調模擬Matlab
- JdbcTemplate調儲存過程JDBC儲存過程
- WIN95 界 面 下 的VC++ 串 口 通 訊 程 序 (轉)C++
- Win7 提示無法檢測到撥號調變解調器Win7
- 基於星座圖整形方法的QAM調製解調系統MATLAB誤位元速率模擬,對比16,32,64,256四種QAM調製方式Matlab
- RFID 基礎/分類/編碼/調製/傳輸
- 調色原理(轉)
- 基於A律壓縮的PCM脈衝編碼調製通訊系統simulink建模與模擬
- win10提示調變解調器報告了一個錯誤怎麼回事 win10系統提示調變解調器報告了一個錯誤如何處理Win10
- Strategy Analytics觀點:蘋果收購英特爾調變解調器業務蘋果
- FM的正交解調法
- PM的正交解調法
- 【調優】CBO基礎