程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> MYSQL客戶機程序4—在運行時獲取連接參數

MYSQL客戶機程序4—在運行時獲取連接參數

編輯:關於MYSQL數據庫
 6.5 客戶機程序4—在運行時獲取連接參數

  現在我們有了容易修改的防止出現錯誤的連接代碼,我們要了解一些如何做某些比使用NULL 連接參數更靈巧的事情,如在運行時允許用戶指定一些值。客戶機程序3由於固定連接參數方面的缺陷,要想更改那些值中的任何一個,都必須編輯源文件並重新編譯。這十分不方便,特別是想使程序用於其他人時。在運行時指定連接參數的一個通用的方法是使用命令行選項。MySQL分發包中的程序接受兩種形式的連接參數,如表6 - 1所示。

  

  與標准的MySQL客戶機程序一致,客戶機程序將接受同樣的格式。這很容易,那是因為客戶機庫包括了實現選項分析的函數。

  除此之外,客戶機程序具有從選項文件中抽取信息的能力。這允許將連接參數放在-/.my. c n f(也就是主目錄中的.my.cnf 文件)中,以便不用在命令行中指定它們。客戶機庫使檢查MySQL選項文件和從它們中抽取任何相關的值變得非常容易。只在程序中增加幾行代碼,就可以使選項文件識別它,並且通過編寫自己的代碼而不必重新改造這個框架來進行操作。附錄E “MySQL程序參考”中說明了選項文件的語法。

  6.5.1訪問選項文件內容

  使用load_default() 函數為連接參數值讀取選項文件, load_default() 尋找選項文件、分析任何感興趣的可選組的內容,以及重新編寫程序的參數向量( a rgv[] 數組),以便把來自於那些組的信息以命令行選項的形式放置在argv[] 的開頭。這就是說,在命令行指定出現的選項。因此,當分析命令選項時,就得到了作為常規選項分析循環部分的連接參數。選項加到argv[] 的開頭而不是加到末尾,所以,如果連接參數真的在命令行指定,它們要比load_defaults() 增加的任何選項晚一些出現(因而忽略)。面的小程序show _ argv 顯示了如何使用load _ defaults ( ),並舉例說明了對參數向量如何做出這樣的修改:

  

  該處理選項文件的代碼包括:

  ■ groups[] 是一個字符串數組,表示所感興趣的選項文件組。對於客戶機程序,始終至少指定“client” ([clIEnt] 組)。數組的最後一個元素必須是NULL。

  ■ my_init() 是load_defaults() 所需的執行一些設置操作的初始化例程。

  ■ load_defaults() 有四個參數:選項文件的前綴(這裡應該始終是“ my”),列出感興趣的可選組的數組、程序參數的數目和向量的地址。不傳數目和向量的值,而是傳地址,因為load_defaults() 需要改變它們的值。特別注意的是,雖然a rgv 是一個指針,但還是要傳& argv ,它是指針的地址。

  show _ argv打印參數兩次,第一次是在命令行指定它們的時候,第二次是在load _ defaults( )修改它們的時候。為了查看load_defaults() 的運行效果,應確信在主目錄中有一個具有[clIEnt] 組指定設置的. my.cnf 文件。假設. my.cnf 文件如下:

  

  有可能會從不在命令行或~ /.my.cnf 文件中的s h o w _ a rgv 所產生的輸出結果中看到一些選項。如果是這樣,它們或許是在系統范圍的選項文件中指定的。在主目錄中讀取.my.cnf 之前,load_defaults() 實際上是在MySQL數據目錄中尋找/ e t c / my.cnf 和my.cnf 文件(在Windows中, load_defaults() 在Windows 系統目錄中尋找文件C : my. c n f、C : MySQLd a t a my.cnf 和my.ini )。

  使用load_defaults() 的客戶機程序幾乎始終是在選項組列表中指定“ c l i e n t”(以便從選項文件中獲取任何通用的客戶機設置),但是也可以為請求自己的程序請求特定值。可將下列代碼:

  

  修改為:

  

  然後將[ show _ argv] 組加到~ / . my.cnf 文件中:

  

  有了這些改變,再次調用show _ argv 就得到了一個不同的結果,如下所示:

  

  參數數組中選項值出現的順序取決於它們在選項文件中列出的順序,而不是選項組在group[] 數組中列出的順序。這意味著將可能在選項文件的[client] 組之後指定程序專有的組。即如果在兩個組中都指定了一個選項,程序專有的值將有更高的優先權。在這個例子中可以看到: 在組[clIEnt] 和[ show _ argv] 中都指定了host 選項,但是因為組[ show _ argv] 在選項文件的最後出現,所以host 值將在參數向量中出現並取得優先權。

  load_defaults() 不是從環境設置中提取值, 如果想使用環境變量的值, 例如MYSQL _ TCP _ PORT 或者MYSQL _ UNIX _ PORT ,就必須使用getenv() 來自己管理。我不想把這個管理能力增加到客戶機中,但這裡有一個例子,介紹了如何檢查幾個標准的與MySQL有關的環境變量值:

  

  在標准MySQL客戶機中,環境變量值的優先權比在選項文件或命令行指定值的優先權要低。如果檢查環境變量的值,並要與約定保持一致,那麼就要在調用load_default() 或者處理命令行選項之前(不是之後)檢查環境。

  6.5.2 分析命令行參數

  現在我們可以把所有的連接參數都放入參數向量,但需要一個分析該向量的方法。getopt_long() 函數就是為此目的設計的。getopt_long() 設在MySQL客戶機庫的內部,因此,無論什麼時候與庫連接都可以訪問它。源文件中要包含getopt.h 頭文件,可以把這個頭文件從MySQL源分發包的include 目錄拷貝到正在開發的客戶機程序所在的目錄中。

  load_defaults() 與安全

  因為有些程序(如p s)可以顯示任何過程的參數列表, load_defaults() 將口令的文本放在參數列表中,所以您可能對它處理窺探的含意表示驚異。這沒有問題,因為ps 顯示原始的a rgv[] 內容,由load_defaults() 創建的任何口令參數都指向為它自己分配的區域,這個區域並不是原始區域的一部分,所以ps 看不見它。另一方面,除非故意清除,否則在命令行指定的口令會在ps 中出現。6 . 5 . 2節“分析命令行參數”介紹了如何去做。下面的程序show_param 使用load_defaults() 讀取選項文件,然後調用getopt_long() 來分

  析參數向量。show_param 舉例說明了通過執行以下操作參數處理的每個階段發生了什麼:

  1) 建立主機名稱、用戶名稱和口令的缺省值。

  2) 打印原始連接參數和參數向量值。

  3) 調用load_defaults() 重新編寫參數向量,反映選項文件內容,然後打印結果向量。

  4) 調用getopt_long() 處理參數向量,然後打印結果參數值和參數向量中的剩余部分。

  show_param 允許使用各種指定的連接參數的方法進行試驗(無論是在選項文件中還是在命令行中),並通過顯示使用什麼值進行連接來查看結果。當實際上我們把參數處理代碼與連接函數do_connect() 連到一起時,show_param 對於預知下一個客戶機程序將要發生什麼是很有用的。

  以下是show_param.c 的代碼:

  

  

  

  

  為了處理參數向量, show _ argv() 使用getopt_long() ,它在循環中調用:

  

  getopt_long() 的前兩個參數是程序的計數參數和向量參數,第三個參數列出了要識別的選項字符。這些是程序選項的短名稱形式。選項字符後可以有冒號、雙冒號或者無冒號,表示選項值必須跟在選項後面、可以跟在選項後面或者不能跟在選項後面。第四個參數long_options 是一個指向可選結構數組的指針,每個可選結構為程序需要支持的選項指定信息。它的目標與第三個參數的可選字符串相類似。每個long_options[] 結構有四個元素,其描述如下:

  ■ 選項的長名稱。

  ■ 選項值。這個值可以是required _ argument、optional _ argument 或者no _ argument,表明選項值是必須跟在選項後面、可以跟在選項後面,還是不能跟在選項後面(它們與第三個參數選項字符串中的冒號、雙冒號或無冒號的作用相同)。

  ■ 標記參數。可用它存儲變量指針。如果找到這個選項, getopt_long() 則把第四個參數指定的值存儲到變量中去。如果標記是NULL,getopt_long() 就把optarg 變量指向下一個選項的任何值,並返回選項的短名稱。long_options[] 數組為所有的選項指定了NULL。那就是說,如果遇到getopt _ long( ),就返回每個參數,以便我們可以在switch語句中來處理它。

  ■ 選項的短(單個字符)名稱。在long_options[] 數組中指定的短名稱必須與作為第三個參數傳遞給getopt_long() 的選項字符串所使用的字母相匹配,否則程序將不能正確處理命令行參數。long_options[] 數組必須由一個所有元素都設為0 的結構所終止。getopt_long() 的第五個參數是一個指向int 變量的指針。getopt_long() 把與最後遇到的選項相符合的long_options[] 結構索引存儲到變量中( show_param 不用這個值做任何事情)。

  請注意,口令選項(指定為--password 或者-p )可以獲得一個選項值,那就是說,如果使用長選項形式可指定為--password 或者--passWord = your_pass,如果使用短選項形式則指定為-p 或者- p your _ pass。可選字符串中“ p” 後面的雙冒號和long_options[] 數組中的optional _ argument 表示了口令值的可選特性。特別是,MySQL客戶機允許在命令行省略口令值,然後提示輸入。這樣避免了在命令行給出口令,它防止其他人通過偷竊看到口令。在寫下一個客戶機程序(客戶機程序4)時,將把口令檢查性能添加進去。下面是show_param 的調用示例和結果輸出(假設~ /.my.cnf 一直與show _ argv 示例有相同的內容):

  

  輸出結果說明從命令行得到主機名(忽略選項文件中的這個值),從選項文件中得到用戶名和口令。getopt_long() 正確分析了選項是在短選項形式( -h host_name )中指定還是在長選項形式( --user = paul ,--passWord = secret )中指定。

  現在讓我們去掉純粹說明選項處理例程是如何工作的這一部分,把剩余部分作為根據選項文件或命令行提供的任何選項而連接到服務器的客戶機的基礎。源文件clIEnt4.c 的代碼如下:

  

  

  

  

  與前面開發的客戶機程序1、客戶機程序2和客戶機程序3比較一下,客戶機程序4具有一些以前沒有的內容:

  ■ 允許在命令行指定數據庫名稱,它緊跟在由getopt_long() 分析的選項的後面。這與MySQL分發包中標准客戶機的行為是一致的。

  ■ 對口令值做了備份之後,刪除參數向量中的任何口令值。這使時間窗口最小化,在時間窗口中命令行所指定的口令對於ps 或其他系統狀態程序是可見的(窗口縮到最小,但並沒有刪除。命令行指定的口令仍然不太安全)。

  ■ 如果給出沒有值的口令選項,則客戶機程序提示用戶用get_tty_passWord() 輸入口令。在客戶機庫中,這是一個實用程序,它提示輸入口令而不在顯示器上回應(客戶機庫充滿了這樣吸引人的東西。因為找到了相關的例程和使用它們的方法,所以有助於從MySQL客戶機程序的源文件中的讀取)。您可能會問:“為什麼不只調用getpass( )呢?”回答是,並不是所有的系統都有這個函數,如Windows。get_tty_passWord() 可以在系統間移植,因為它被配置為適應各種不同系統。

  客戶機程序4按照指定的選項來響應。假設沒有使事件復雜化的選項文件。如果無參數調用客戶機程序4,則連接到localhost,並把UNIX 注冊名和無口令傳遞到服務器中。相反,如果像介紹的那樣調用客戶機程序4,則提示輸入口令(沒有直接以-p 開頭的口令值),連接到some _ host,並將用戶名some_user 和鍵入的口令都傳遞到服務器:

  

  客戶機程序4也把數據庫名some_db 傳遞給do _ connect( ),成為當前數據庫。如果沒有選項文件,則處理它的內容並用來改變參數連接。

  早期,我們曾熱衷於封裝代碼,創建包裝函數,目的是斷開與服務器的連接和從服務器的連接斷開。詢問是否把分析選項部分放置到包裝函數中也是合理的。我想這是可能的,但並不想去做。選項分析代碼與連接代碼在程序間並不一致:程序經常支持除了標准選項之外

  的其他選項,不同的程序很可能支持其他選項的不同設置。這就使選項處理循環標准化的函數很難編寫。而且,與連接的建立不同,在它的執行過程中程序可以希望進行多次(因而是好的封裝候選者),而選項分析只在程序開始時執行一次。

  迄今為止,我們所做的工作完成了每個MySQL客戶機程序所必須做的事情:用適當的參數與服務器相連接。當然應該知道如何連接,現在知道怎麼做了,並且處理的細節由客戶機程序框架( clIEnt4.c )來實現,因此就不必再去考慮了。這就是說可以集中精力干真正感興趣的事情—訪問數據庫的內容。應用程序中所有的真正功能將在do_connect() 調用和do_disconnect() 調用之間發生,但是我們現在所擁有的是用於建立可為許多不同客戶機程序使用的基本框架。編寫一個新程序,要做到以下幾點:

  1) 制作一個clIEnt4.c 的備份。

  2) 如果接受其他選項而不是clIEnt4.c 支持的標准選項,那麼修改處理選項循環。

  3) 在連接和斷開調用之間加上自己的應用程序代碼。

  這樣就算完成了。

  構造客戶機程序框架的目的是,很容易地建立和斷開連接,以便集中精力干真正想做的事情。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved