網絡編程小貼士

網絡編程小貼士

( 作者:mikespook | 發佈日期:2003-7-4 | 瀏覽次數:321 )

關鍵字:網絡,IP,主機名
  本文已投稿《黑客安全基地》。文章爲《黑客安全基地》所有,未經《黑客安全基地》同意不得轉載。謝謝合作!

  下面給大家介紹幾個常用的網絡編程小貼士。爲了方便起見,我將用C++ Builder 5來做演示程序。大家首先應該在C++ Builder 5中做一下配製。
  對於小貼士一至四,你應該在Project Options中的Directories/Conditionals選項卡里添加“$(BCB)/lib/PSDK”到Library path中(圖1)。
2003-7-4網絡編程小貼士1.jpg
  並且在頭文件(<窗體>.h)中添加“#inclucde “wininet.h””。在<項目>.cpp文件中加入“USELIB(“wininet.lib”);”。
  對於小貼士五、六,只要在頭文件(<窗體>.h)加入“#include “winsock2.h””即可。
  在下面的例子中sbMsg是TstatusBar的實例。EdtURL、edtHostName是Tedit的實例。btnTip1、btnTip2、btnTip3、btnTip4、btnTip5、btnTip6是Tbutton的實例。

一、 嘗試進行網絡連接
  要用的函數:InternetAttemptConnect
  函數原形:DWORD InternetAttemptConnect(DWORD dwREserved);
  這個函數可以說非常簡單,只是嘗試計算機連接到網絡。並不考慮是用什麼方式連接。當成功連接到網絡的時候,函數返回ERROR_SUCCESS,也就是0。函數的參數永遠都是0。有一點需要注意的是,當計算機是用“小貓”也就是撥號的方式上網的時候,在執行InternetAttemptConnect這個函數時,會自動激活撥號連接功能。這也就是很多軟件使用的撥號連接功能。比如Foxmail和FlashGet。
  程序如下:
void __fastcall TfrmMain::btnTip1Click(TObject *Sender)
{
        if(ERROR_SUCCESS==InternetAttemptConnect(0))
                sbMsg->SimpleText = "網絡連接成功!";
        else
                sbMsg->SimpleText = "網絡連接失敗!";
}

二、 檢查遠程主機狀態
  要用的函數:InternetCheckConnection
  函數原形:BOOL InternetCheckConnection(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved);
  這個函數的作用和PING命令是一樣的,可以檢查遠程主機是否連接。如果連接成功返回TRUE,如果連接失敗返回FALSE。參數lpszUrl是遠程主機的IP地址或URL。DwFlags只可設置一個值FLAG_ICC_FORCE_CONNECTION,也就是0x00000001。DwReserved是保留參數,只能設置爲0。
  程序如下:
void __fastcall TfrmMain::btnTip2Click(TObject *Sender)
{
        if(InternetCheckConnection(edtURL->Text.c_str(), FLAG_ICC_FORCE_CONNECTION, 0))
                sbMsg->SimpleText = "網絡連接成功!";
        else
                sbMsg->SimpleText = "網絡連接失敗!";
}
三、 檢查本地網絡連接狀態並取得網絡連接方式
  要用的函數:InternetGetConnectedState
  函數原形:BOOL InternetGetConnectedState(LPDWORD lpdwFlags,DWORD dwReserved);
  這個函數的功能是很強的。它可以:
  1. 判斷網絡連接是通過網卡還是通過調治解調器
  2. 是否通過代理上網
  3. 判斷連接是On Line還是Off Line
  4. 判斷是否安裝“撥號網絡服務”
  5. 判斷調治解調器是否正在使用
  這裏我們只需要使用它的第一條功能。參數lpdwFlags返回當前網絡狀態。這裏我們只要用下面兩個標誌進行判斷。
  INTERNET_CONNECTION_MODEM 通過調治解調器連接網絡
  INTERNET_CONNECTION_LAN 通過局域網連接網絡
  參數dwReserved依然是保留參數,設置爲0即可。
  當函數返回TRUE時說明連接到網絡,否則返回FALSE。
  程序如下:
void __fastcall TfrmMain::btnTip3Click(TObject *Sender)
{
        DWORD dwFlag;
        if(!InternetGetConnectedState(&dwFlag, 0))
                sbMsg->SimpleText = "網絡未連接。";
        else
        if(dwFlag & INTERNET_CONNECTION_MODEM)
                sbMsg->SimpleText = "採用調治解調器上網。";
        else
        if(dwFlag & INTERNET_CONNECTION_LAN)
                sbMsg->SimpleText = "採用網卡上網。";
}
四、 判斷是否使用代理連接
  依然使用上面的這個InternetGetConnectedState函數。當lpdwFlags的標誌判斷爲INTERNET_CONNECTION_PROXY的時候,說明本地使用代理連接到網絡。
  程序如下:
void __fastcall TfrmMain::btnTip4Click(TObject *Sender)
{
        DWORD dwFlag;
        if(!InternetGetConnectedState(&dwFlag, 0))
                sbMsg->SimpleText = "網絡未連接。";
        else
        if(dwFlag & INTERNET_CONNECTION_PROXY)
                sbMsg->SimpleText = "使用代理連接。";
        else
                sbMsg->SimpleText = "未使用代理連接。";
}
五、 取得本機IP地址
  要用的函數:gethostname、gethostbyname、inet_ntoa
  函數原形: int gethostname(char FAR *name,int namelen);
  struct hostent FAR *gethostbyname(const char FAR *name);
  char FAR * inet_ntoa(struct in_addr in);
  函數gethostname可以取得本地計算機主機名。參數name就是調用函數後保存主機名的字符指針。參數namelen是name參數的長度。
函數gethostbyname可以利用參數name傳入的主機名返回一個hostent結構。這個結構的原形如下:
struct hostent {
  char FAR *       h_name;
  char FAR * FAR * h_aliases;
  short            h_addrtype;
  short            h_length;
  char FAR * FAR * h_addr_list;
};
  其中h_name返回主機名;h_aliases返回主機別名;h_addrtype返回IP地址的類型;h_length返回IP地址長度;h_addr_list返回IP地址。這裏特別要說明一下的是h_addr_list。因爲一臺計算機可能有多個有效的IP地址,所以h_addr_list實際上是一個數組。並且h_addr_list返回的是以網絡位順序表示的IP地址,還需要通過inet_ntoa函數轉化爲以“.”做分隔的IP地址。
  函數inet_ntoa轉化網絡位順序表示的IP地址到“xxx.xxx.xxx.xxx”這種形式的IP地址。參數in是一個in_addr結構。我們只要知道怎麼使用inet_ntoa函數即可,如果想了解更多的內容可以去查MSDN。
  程序如下:
void __fastcall TfrmMain::btnTip5Click(TObject *Sender)
{
        char cHostName[256];
        AnsiString strAdd;
        gethostname(cHostName, sizeof(cHostName));
        hostent *Host = gethostbyname(cHostName);
        if(NULL==Host)
                sbMsg->SimpleText = "獲取IP地址錯誤。";
        else
        {
                in_addr addr;
                for(int i = 0; Host->h_addr_list[i] != 0; ++i) //注意這裏的循環
                {
                        memcpy(&addr, Host->h_addr_list[i], sizeof(in_addr));
                        strAdd = strAdd + " " + StrPas(inet_ntoa(addr));
                }
                sbMsg->SimpleText = "本機IP地址爲"+strAdd;
        }
}
  這裏要特別說明一下的就是那個循環。前面說過了,因爲一臺計算機可能有多個有效的IP地址,所以h_addr_list實際上是一個數組。所以我們要利用這麼一個循環取得本地主機所有可能的IP。
六、 遠程主機名到IP地址的轉化
  有了前面的講解,要進行遠程主機名到IP地址的轉化可以說是易如反掌。只要對程序進行下面的修改即可。
  程序如下:
void __fastcall TfrmMain::btnTip6Click(TObject *Sender)
{
        char cHostName[256];
        AnsiString strAdd;
/*
        注意這裏和小貼士五中的區別
gethostname(cHostName, sizeof(cHostName));
hostent *Host = gethostbyname(cHostName);
*/
        hostent *Host = gethostbyname(edtHostName->Text.c_str());
        if(NULL==Host)
                sbMsg->SimpleText = "獲取IP地址錯誤。";
        else
        {
                in_addr addr;
                for(int i = 0; Host->h_addr_list[i] != 0; ++i)
                {
                        memcpy(&addr, Host->h_addr_list[i], sizeof(in_addr));
                        strAdd = strAdd + " " + StrPas(inet_ntoa(addr));
                }
                sbMsg->SimpleText ="計算機" + edtHostName->Text + "的IP地址爲"+strAdd;
        }
}
  這裏補充說明以下,當cHostName爲NULL的時候,函數取得的依然是本地主機的IP地址。

  這六個小貼士是網絡編程中最常用的,也是最好用的小技巧。用好,用精的話,你可以寫出許許多多好用的小工具出來。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章