Windows下C语言网络编程快速入门
C語言的學(xué)習(xí),一般的方式是,先學(xué)C,然后是C++,最好還要有匯編語言和微機(jī)原理基礎(chǔ),然后才是Visual C++。這樣的方式,對學(xué)習(xí)者來說,要花費(fèi)很多時間和耐力。而在學(xué)校教學(xué)中,也沒有時間深入學(xué)習(xí)Windows編程的實(shí)用技術(shù)了。
其實(shí),具有了C語言基礎(chǔ)后,再有一些基本的C++類的概念,就可以直接學(xué)習(xí)Windows C編程了。
一、走近Windows C語言
很多語言都把顯示一個“Hello,World!”做為第一個入門程序, C語言的第一個程序是這樣的:
#include<stdio.h>
main()
{
printf(“Hello,World!”);
}
如果把main函數(shù)寫成帶參數(shù)的main函數(shù),應(yīng)該是:
#include<stdio.h>
main(int arge,char *argv[])
{
printf(“Hello,World!”);
}
Windows C的第一個程序和這個程序在形式和原理上都是一致的,只是有兩點(diǎn)不同:
1. 主函數(shù)接收的形參不只是命令行中的字符串的個數(shù)和字符串的首地址。
2. C語言的很多函數(shù)在Windows C中都可以繼續(xù)使用,但象printf()屏幕顯示等函數(shù)就不能繼續(xù)使用了。因?yàn)閃indows是多任務(wù)操作系統(tǒng),屏幕已不再為某一個應(yīng)用程序所獨(dú)有,Windows C應(yīng)用程序要顯示字符串,需要使用Windows提供的API函數(shù),開自己的窗口
下面是一個最簡單的,顯示“Hello,World!”的Windows C程序:
#include<windows.h>
APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
MessageBox(NULL,"Hello,World!","第一個Windows C程序",MB_OK|MB_ICONASTERISK);
}
主函數(shù)的形參有四個:
1) Hinstance:接收程序運(yùn)行時當(dāng)前實(shí)例的句柄;
2) HprivInstance:前一個實(shí)例的句柄;
3) LpCmdLine:程序命令行指針;
4) NcmdShow:一個用來指定窗口顯示方式的整數(shù)。
這幾個參數(shù)的使用我們會在深入的學(xué)習(xí)中介紹的。
顯示Hello,Word!字符串,我們使用了一個MessageBox函數(shù),這個函數(shù)會在屏幕上顯示一個對話框,它的原型是:
int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UNIT uType)
四個參數(shù)分別是:
1) HWnd:父窗口的句柄;
2) LpText:要顯示字符串的指針;
3) LpCaption:對話框標(biāo)題字符串的指針;
4) UType:顯示在對話框上的小圖標(biāo)的類型。
使用這個函數(shù)要包含windows.h頭文件。
調(diào)試一下,怎么樣?窗口上彈出了一個“第一個Windows C程序”對話框,上面有一行字:“Hello,World!”。
世界真的很美好啊!!
深入編程:
在C語言中,函數(shù)的聲明,如果沒有指明返回值類型,缺省值為void,這個程序的主函數(shù)就沒有返回值。不過,在Windows編程時,我們最好養(yǎng)成個好習(xí)慣,指明函數(shù)的返回值類型,因?yàn)樵贑++中,函數(shù)返回值類型是不可以缺省的。而我們在Windows C編程時,還是會用到C++的一些概念,這樣做,有利于以后深入地學(xué)習(xí)。
規(guī)范一點(diǎn)的程序應(yīng)該是這樣的:
#include<windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
MessageBox(NULL,"Hello,World!","第一個Windows C程序",MB_OK|MB_ICONASTERISK);
return 0;
}
這里,我們聲明的類型為int型,并且返回一個值0,這樣的函數(shù)就可以使用在復(fù)雜一點(diǎn)的函數(shù)調(diào)用中了。
在這一節(jié)中,我們有幾處都提到了句柄的概念,句柄和指針的概念不同,它是作為操作系統(tǒng)內(nèi)部索引表中的一個值來使用的,這樣可以防止應(yīng)用程序直接訪問名對象的內(nèi)部結(jié)構(gòu),體現(xiàn)了Windows資源管理的優(yōu)越性。譬如說,一個窗口找開之后,好對應(yīng)內(nèi)存中的一個內(nèi)存塊,這個窗口所在的內(nèi)存快地址往往會由操作系統(tǒng)做動態(tài)的調(diào)整,但其卻不會隨之變化。不過,通過它可以訪問這個窗口,所以在使用的時候,可以把它當(dāng)做指針一樣看待。
二、 獲取本地計(jì)算機(jī)的主機(jī)名和IP地址
和C語言一樣,函數(shù)是Windows C編程的最基本的單位。不過,Windows C主要使用API函數(shù),而網(wǎng)絡(luò)編程則主要使用Winsock提供的API函數(shù)。
Winsock是90年代初,為了方便網(wǎng)絡(luò)編程,由Microsoft聯(lián)合了其他幾家公司共同制定的一套WINDOWS下的網(wǎng)絡(luò)編程接口,它是通過C語言的動態(tài)鏈接庫方式提供給用戶及軟件開發(fā)者的,主要由winsock.h頭文件和動態(tài)鏈接庫winsock.dll組成,目前有兩個版本:Winsock1.1和Winsock2.0。
在Win32平臺上,訪問眾多的基層網(wǎng)絡(luò)協(xié)議,Winsock是首選接口。
用Visual C++6.0編譯Windows C程序,使用Winsock API函數(shù)時,首先要把wsock32.lib添加到它的庫模塊中,否剛在鏈接的時候,會出現(xiàn)“error LNK2001”錯誤。添加wsock32.lib的具體步驟是:打開工程菜單,選擇設(shè)置,在彈出的Project settings對話框中,點(diǎn)擊link選項(xiàng)卡,然后在對象/庫模塊文本框中添加wsock32.lib。
最簡單的網(wǎng)絡(luò)編程是獲取本機(jī)的主機(jī)名和IP地址,這個程序使用了WSAStart()、WSAClenaup()、gethostname()、gethostbyname()四個winsock API函數(shù),這四個函數(shù)的功能和使用方法介紹如下:
1. WSAStartup():
【函數(shù)原型】
int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);
【使用說明】
每一個使用winsock的應(yīng)用程序,都必須進(jìn)行WSAStart函數(shù)調(diào)用,并且只有在調(diào)用成功之后才能使用其它的winsock網(wǎng)絡(luò)操作函數(shù)。
WVersionRequired:<輸入>表示欲使用的Winsock版本,這是一個WORD類型的整數(shù),它的高位字節(jié)定義的是次版本號,低位字節(jié)定義的是主版本號。
LpWSAData:<輸出>是一個指向WSADATA資料的指針。這個資料我們一般不使用。
返回值:調(diào)用成功返回0;否則,返回出錯信息。
2. WSAClenaup():
【函數(shù)原型】
int PASCAL FAR WSACleanup(void);
【使用說明】
winsock使用后,要調(diào)用WSACleanup函數(shù)關(guān)閉網(wǎng)絡(luò)設(shè)備,以便釋放其占用的資源。
3.gethostname()
【函數(shù)原型】
int PASCAL FAR gethostname (char FAR * name, int namelen);
【使用說明】
該函數(shù)可以獲取本地主機(jī)的主機(jī)名,其中:
name:<輸出>用于指向所獲取的主機(jī)名的緩沖區(qū)的指針。
Namelen:<輸入>緩沖區(qū)的大小,以字節(jié)為單位。
返回值:若無錯誤,返回0;否則,返回錯誤代嗎。
4.gethostbyname()
【函數(shù)原型】
struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);
【使用說明】
該函數(shù)可以從主機(jī)名數(shù)據(jù)庫中得到對應(yīng)的“主機(jī)”。
該函數(shù)唯一的參數(shù)name就是前面調(diào)用函數(shù)gethostname()得到的主機(jī)名。若無錯誤,剛返回一個指向hostent結(jié)構(gòu)的批針,它可以標(biāo)識一個“主機(jī)”列表。
Hostent結(jié)構(gòu)定義如下:
Struct hostent
{
char FAR * h_name;
char FAR FAR ** h_aliases;
short h_addrtype;
char FAR FAR ** h_addr_list;
}
其中:
h_name:<輸入>主機(jī)名地址(PC)。
h_aliases:一個由主機(jī)備用名組成的空中止數(shù)組。
H_addrtype:返回地址的類型,對于Winsock,這個域總是PF_INET。
H_lenth:每個地址的長度(字節(jié)數(shù)),對應(yīng)于PF_INET域應(yīng)該為4。
H_addr_list:應(yīng)該以空指針結(jié)尾的主機(jī)地址的列表,返回的地址是以網(wǎng)絡(luò)順序排列的。
其中,h_addr_list[0]存放的就是本地主機(jī)的4個字節(jié)的IP地址,即:
h_addr_list[0][0].h_addr_list[0][1].h_addr_list[0][2].h_addr_list[0][3]
一個簡單的用消息框顯示主機(jī)名和IP地址的源程序如下:
#include<winsock.h>
int WSA_return;
WSADATA WSAData;
HOSTENT *host_entry;
char host_name[256];
char host_address[256];
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
WSA_return=WSAStartup(0x0101,&WSAData);
if(WSA_return==0)
{
gethostname(host_name,256);
host_entry=gethostbyname(host_name);
if(host_entry!=0)
{
wsprintf(host_address,"%d.%d.%d.%d",
(host_entry->h_addr_list[0][0]&0x00ff),
(host_entry->h_addr_list[0][1]&0x00ff),
(host_entry->h_addr_list[0][2]&0x00ff),
(host_entry->h_addr_list[0][3]&0x00ff));
MessageBox(NULL,host_address,host_name,MB_OK);
}
}
WSACleanup();
return 0;
}
?
深入編程:
前面顯示IP地址的時候,我們使用的是消息框,規(guī)范一點(diǎn)的編程應(yīng)該使用對話框,如何編輯一個對話框,很多書中都有介紹,編輯的對話框可參考圖5的運(yùn)行界面。
頭文件Get_IP.h如下:
BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam);
這個程序只使用了一個對話框過程,一般把這個過程的聲明放在頭文件中。
源程序Get_IP.c:
#include<winsock2.h>
#include"Get_IP.h"
#include"resource.h" //這個頭文件在創(chuàng)建資源的時候會自動生成,
//并會在插入資源時自動生成控件標(biāo)識號.
int WSA_return;
WSADATA WSAData;
HOSTENT *host_entry;
char host_name[256];
char host_address[256];
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
WSA_return=WSAStartup(0x0101,&WSAData);
if(WSA_return==0)
{
gethostname(host_name,256);
host_entry=gethostbyname(host_name);
if(host_entry!=0)
{
wsprintf(host_address,"%d.%d.%d.%d",
(host_entry->h_addr_list[0][0]&0x00ff),
(host_entry->h_addr_list[0][1]&0x00ff),
(host_entry->h_addr_list[0][2]&0x00ff),
(host_entry->h_addr_list[0][3]&0x00ff));
}
}
WSACleanup();
DialogBox(hInstance,"DIALOG1",NULL,(DLGPROC)Hostname_ipDlgPro);
return 0;
}
BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message,
WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
return(TRUE);
case WM_COMMAND:
if(LOWORD(wParam)==IDOK)
{
SetDlgItemText(hDlg,IDC_EDIT1,host_name);
SetDlgItemText(hDlg,IDC_EDIT2,host_address);
SetDlgItemText(hDlg,IDCANCEL,"確定");
}
if(LOWORD(wParam)==IDCANCEL)
EndDialog(hDlg,TRUE);
return(TRUE);
break;
}
return(FALSE);
}
三、利用VisualC++6.0編譯Windows C程序
利用Visual C++6.0編譯Windows C程序一般要經(jīng)過以下四個步驟:新建項(xiàng)目、添加代碼、添加資源和編譯鏈接。下面我們簡單地介紹一下程序上面介紹的規(guī)范的獲取本機(jī)的主機(jī)名和IP地址程序的編譯過程:
(一) 新建項(xiàng)目
1.啟動MicrosoftVisualC++,然后在【文件】菜單中先擇【新建】命令,彈出如圖1所示的【新建】對話框:
圖1 |
2.在【新建】對話框中,系統(tǒng)打開的是默認(rèn)的【工程】選項(xiàng)卡,【工程】選項(xiàng)卡左側(cè)的列表框中有多種建立工程的方式,我們選中“Win32 Application”選項(xiàng)。
3. 在【位置】文本框中輸入新建工程的路徑(例如:F:/),在【工程】文本框中輸入工程名稱(例如:Get_IP)。
4. 選中【平臺】列表框中的Win32復(fù)選框,然后單擊【確定】按鈕。
5. 在隨后的對話框中,都選擇默認(rèn)設(shè)置,完成后,進(jìn)入圖2示界面:
圖2 |
(二) 添加代碼
在VisualC++6.0中,源代碼一般存放在源代碼文件和頭文件中,往項(xiàng)目中添加源代碼是非常方便的,為項(xiàng)目新建一個源代碼文件一般要按下述方法操作:
1. 選擇【工程】|【添加工程】|【新建】選項(xiàng),彈出圖3所示【新建】對話框:
圖3 |
2. 在對話框的【文件】選項(xiàng)卡中,左側(cè)的列表框選中“C++ Source File”選項(xiàng),右側(cè)選中【添加工程】復(fù)選框,并在【文件】文本框中輸入源文件名(例如:Get_IP.c)。
3. 單擊【確定】按鈕,【新建】對話框?qū)⒈婚],用戶就可以在新建的Get_IP.c中輸入程序的源代碼了。
4. 添加頭文件Get_IP.h的方法和上面所述過程一樣,只是在【文件】選項(xiàng)卡中,左側(cè)的列表框要先中“C/C++ Header File”選項(xiàng)。在【文件】文本框中輸入頭文件名(例如:Get_IP.h)。
(三) 添加資源
在添加資源前,必須在項(xiàng)目中先添加一個資源文件,然后可利用Visual C++6.0提供的資源編輯器為項(xiàng)目新建一個資源,具體步驟如下:
1. 選擇【工程】|【添加工程】|【新建】選項(xiàng),彈出圖3所示【新建】對話框。
2. 在對話框的【文件】選項(xiàng)卡中,左側(cè)的列表框選中“Rsource Script”選項(xiàng),右側(cè)選中【添加工程】復(fù)選框,并在【文件】文本框中輸入資源文件名(例如:Get_IP.rc)。
3. 單擊確定,回到主窗口后,選擇【插入】|【資源】選項(xiàng),打開【插入資源】對話框,如圖4所示, 在【資源類型】列表框中選中“Dialog”選項(xiàng),單擊【新建】按鈕,返回主窗口后,即可利用對話框編輯器進(jìn)行編輯了。編輯后的對話框如圖
圖4 |
圖5 |
(四) 編譯鏈接
在添加了源代碼與資源文件后,就可以對程序編譯連接了,可按Ctrl+F7鍵編譯,按F7鍵連接,按Ctrl+F5鍵運(yùn)行程序。在連接前是要注意,資源文件Get_IP.rc也要進(jìn)行編譯。
由于這個程序引用了Winsock API函數(shù),在編譯連接前,還要添加wsock32.dll,具體方法前面已經(jīng)介紹過,這里就不再贅述了。
一點(diǎn)看法:
利用C語言編寫Windows應(yīng)用程序有兩種方式:一種是Windows C編程方式,另一種是Visual C++編程方式。在一般情況下,Visual C++編程方式編寫的程序源代碼量小、開發(fā)時的工作量小、工作難度也較小,但編譯后的代碼量較大,運(yùn)行速度略低;而Windows C編程方式編寫的程序源代碼量雖然較大,但可執(zhí)行代碼效率高。隨著技術(shù)的進(jìn)步,Visual C++編程方式已被廣泛采用,但象網(wǎng)絡(luò)編程等一些對速度要求高、對硬件操作較多的程序,大多數(shù)還是用Windows C編程方式開發(fā)的。另外,學(xué)習(xí)Windows C程序設(shè)計(jì),還有助于更深入地了解Windows的內(nèi)幕和Windows API。
從教學(xué)角度講,在學(xué)生具備了C語言和其它一些前導(dǎo)課程基礎(chǔ)后,直接進(jìn)入Windows C網(wǎng)絡(luò)編程等實(shí)用編程技術(shù)課程,不僅可以讓學(xué)生盡早地接觸到前沿的實(shí)用編程技術(shù),而且還可以極大地調(diào)動學(xué)生的學(xué)習(xí)積極性,在有限的時間里,學(xué)到更多的知識和技術(shù)。
圖1 |
2.在【新建】對話框中,系統(tǒng)打開的是默認(rèn)的【工程】選項(xiàng)卡,【工程】選項(xiàng)卡左側(cè)的列表框中有多種建立工程的方式,我們選中“Win32 Application”選項(xiàng)。
3. 在【位置】文本框中輸入新建工程的路徑(例如:F:/),在【工程】文本框中輸入工程名稱(例如:Get_IP)。
4. 選中【平臺】列表框中的Win32復(fù)選框,然后單擊【確定】按鈕。
5. 在隨后的對話框中,都選擇默認(rèn)設(shè)置,完成后,進(jìn)入圖2示界面:
圖2 |
(二) 添加代碼
在VisualC++6.0中,源代碼一般存放在源代碼文件和頭文件中,往項(xiàng)目中添加源代碼是非常方便的,為項(xiàng)目新建一個源代碼文件一般要按下述方法操作:
1. 選擇【工程】|【添加工程】|【新建】選項(xiàng),彈出圖3所示【新建】對話框:
圖3 |
2. 在對話框的【文件】選項(xiàng)卡中,左側(cè)的列表框選中“C++ Source File”選項(xiàng),右側(cè)選中【添加工程】復(fù)選框,并在【文件】文本框中輸入源文件名(例如:Get_IP.c)。
3. 單擊【確定】按鈕,【新建】對話框?qū)⒈婚],用戶就可以在新建的Get_IP.c中輸入程序的源代碼了。
4. 添加頭文件Get_IP.h的方法和上面所述過程一樣,只是在【文件】選項(xiàng)卡中,左側(cè)的列表框要先中“C/C++ Header File”選項(xiàng)。在【文件】文本框中輸入頭文件名(例如:Get_IP.h)。
(三) 添加資源
在添加資源前,必須在項(xiàng)目中先添加一個資源文件,然后可利用Visual C++6.0提供的資源編輯器為項(xiàng)目新建一個資源,具體步驟如下:
1. 選擇【工程】|【添加工程】|【新建】選項(xiàng),彈出圖3所示【新建】對話框。
2. 在對話框的【文件】選項(xiàng)卡中,左側(cè)的列表框選中“Rsource Script”選項(xiàng),右側(cè)選中【添加工程】復(fù)選框,并在【文件】文本框中輸入資源文件名(例如:Get_IP.rc)。
3. 單擊確定,回到主窗口后,選擇【插入】|【資源】選項(xiàng),打開【插入資源】對話框,如圖4所示, 在【資源類型】列表框中選中“Dialog”選項(xiàng),單擊【新建】按鈕,返回主窗口后,即可利用對話框編輯器進(jìn)行編輯了。編輯后的對話框如圖
圖4 |
圖5 |
(四) 編譯鏈接
在添加了源代碼與資源文件后,就可以對程序編譯連接了,可按Ctrl+F7鍵編譯,按F7鍵連接,按Ctrl+F5鍵運(yùn)行程序。在連接前是要注意,資源文件Get_IP.rc也要進(jìn)行編譯。
由于這個程序引用了Winsock API函數(shù),在編譯連接前,還要添加wsock32.dll,具體方法前面已經(jīng)介紹過,這里就不再贅述了。
一點(diǎn)看法:
利用C語言編寫Windows應(yīng)用程序有兩種方式:一種是Windows C編程方式,另一種是Visual C++編程方式。在一般情況下,Visual C++編程方式編寫的程序源代碼量小、開發(fā)時的工作量小、工作難度也較小,但編譯后的代碼量較大,運(yùn)行速度略低;而Windows C編程方式編寫的程序源代碼量雖然較大,但可執(zhí)行代碼效率高。隨著技術(shù)的進(jìn)步,Visual C++編程方式已被廣泛采用,但象網(wǎng)絡(luò)編程等一些對速度要求高、對硬件操作較多的程序,大多數(shù)還是用Windows C編程方式開發(fā)的。另外,學(xué)習(xí)Windows C程序設(shè)計(jì),還有助于更深入地了解Windows的內(nèi)幕和Windows API。
從教學(xué)角度講,在學(xué)生具備了C語言和其它一些前導(dǎo)課程基礎(chǔ)后,直接進(jìn)入Windows C網(wǎng)絡(luò)編程等實(shí)用編程技術(shù)課程,不僅可以讓學(xué)生盡早地接觸到前沿的實(shí)用編程技術(shù),而且還可以極大地調(diào)動學(xué)生的學(xué)習(xí)積極性,在有限的時間里,學(xué)到更多的知識和技術(shù)。
總結(jié)
以上是生活随笔為你收集整理的Windows下C语言网络编程快速入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MatConvnet工具箱文档翻译理解(
- 下一篇: 报表式CListCtrl的使用详解初稿