實驗一 Winsock編程接口實驗
網(wǎng)絡(luò)程序設(shè)計實驗報告實驗名稱:winsock 編程接口實驗__________ 實驗類型:驗證型實驗______ ___ 指導(dǎo)教師:賈浩 ________________
網(wǎng)絡(luò)程序設(shè)計
實驗報告
實驗名稱:winsock 編程接口實驗__________ 實驗類型:驗證型實驗______ ___ 指導(dǎo)教師:賈浩 ___________________
專業(yè)班級: 信安0904_________________ 姓 名:_諶軍________________________ 學(xué) 號:_20092036___________________ 電子郵件:_448149700@qq.com__________ 實驗地點:_東六a 座4--17______________
實 驗 日 期: 2012 年 3 月 11 日
實驗成績:__________________________
,二、實驗設(shè)計
(一)實驗要求如下:
1、編寫程序能同時實現(xiàn)對多個域名的解析。比如在控制臺輸入:getip www.163.com www.swust.edu.cn , 能輸出www.163.com 和 www.swust.edu.cn 對應(yīng)的IP 地址列表。
2、編寫程序獲取并輸出本地主機(jī)的所有適配器的IP 地址,子網(wǎng)掩碼,默認(rèn)網(wǎng)關(guān),MAC 地址。
(二)設(shè)計:
1、 要實現(xiàn)對域名的解析,最主要是對gethostbyname ()函數(shù)的理解和應(yīng)用。
函數(shù)原型為:
struct hostent *gethostbyname(const char *name);
name 為指向主機(jī)名的指針,它一般由函數(shù)gethostname 返回。
函數(shù)返回對應(yīng)于給定主機(jī)名的包含主機(jī)名字和地址信息的hostent 結(jié)構(gòu)指針,該結(jié)構(gòu)格式如下:
struct hostent{
char FAR* h_name;
char FAR* FAR* h_aliases;
short h_addrtype;
short h_length;
char FAR* FAR* h_addr_list;
};
由于已知主機(jī)名(即輸入的域名),所以只要調(diào)用該函數(shù)就能得到ip 地址列表。 根據(jù)分析可得出程序流程圖如下:
,2、要得到本地主機(jī)的所有適配器的IP 地址,子網(wǎng)掩碼,默認(rèn)網(wǎng)關(guān),MAC 地址等信息,主要是對GetAdaptersInfo()函數(shù)的理解和應(yīng)用。
該函數(shù)可以獲取本地主機(jī)的所有適配器信息,并保存在pAdapterInfo 所指向的鏈表中。 函數(shù)原型為:
DWORD GetAdaptersInfo(
PIP_ADAPTER_INFO pAdapterInfo, // buffer to receive data
PULONG pOutBufLen // size of data returned
);
IP_ADAPTER_INFO的定義如下:
typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;
DWORD ComboIndex;
char AdapterName[MAX_ADAPTER_NAME_LENGTH 4];
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH 4];
UINT AddressLength;
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD Index;
UINT Type;
UINT DhcpEnabled;
PIP_ADDR_STRING CurrentIpAddress;
IP_ADDR_STRING IpAddressList;
IP_ADDR_STRING GatewayList;
IP_ADDR_STRING DhcpServer;
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
通過調(diào)用該函數(shù)就可以得到所有適配器信息。
流程圖如下:
三、實驗過程(包含實驗結(jié)果)
1. 實驗步驟如下:
(1)建立一個C 程序工程,并建立同名的C 文件;
(2)將教材上獲取本機(jī)IP 等信息代碼輸入;
(3)將::gethostname(szHost, 256)改為cout<<”請輸入主機(jī)名”<
(4)為主函數(shù)中的所有代碼加上while 循環(huán),從而實驗多次域名的輸入。
(5)編譯,調(diào)試,運行程序,檢驗程序運行結(jié)果。
(6)思考,分析實驗結(jié)果,編寫實驗報告。
實驗編譯及鏈接錯誤:無。
解決方案:無。
實驗結(jié)果:如下截圖結(jié)果
2. 實驗步驟如下:
(1)建立名為LocalHostInfo 的一個C 程序工程,并建立同名的文件;
(2)將教材上獲取本機(jī)ip 地址,子網(wǎng)掩碼,網(wǎng)關(guān)ip 和本機(jī)MAC 地址代碼錄入;
(3)編譯,調(diào)試,運行程序,檢驗程序運行結(jié)果。
(4)思考,分析實驗結(jié)果,編寫實驗報告。
實驗編譯及鏈接錯誤:無。
解決方案:無。
實驗結(jié)果:如下截圖為運行程序后的結(jié)果:
四、討論與分析
1) Winsock 初始化的作用是什么?
答:作用是為了式程序能夠使用一些底層的API 函數(shù),用來完成功能
2) 給出GetAdaptersInfo ()函數(shù)的正確使用方法
DWORD GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, //指向一個緩沖區(qū),用來取得IP_ADAPTER_INFO 結(jié)構(gòu)的列表
PULONG pOutBufLen //用來指定上面的緩沖區(qū)的大小,如果大小不夠,此參數(shù)返回所需大小
)//函數(shù)調(diào)用成功返回ERROR_SUCCESS
3) 域名解析時出現(xiàn)域名對應(yīng)多個IP ,請解釋原因。
因為一臺主機(jī)上可能會對應(yīng)多個IP 地址如(筆記本上的無線網(wǎng)卡上對應(yīng)了一個IP 地址而在有線上也對應(yīng)了一個IP 地址)
五、實驗者自評(從實驗設(shè)計、實驗過程、對實驗知識點的理解上給出客觀公正的自我評價)
這次實驗使我對書本上的知識有了更深的理解,對于這些重要的API 函數(shù)的調(diào)用也有了一個更加明確的理解,除此之外,我還對套接字、端口、IP 地址之間的關(guān)系有了初步的理解, 在以后的實驗中,我會更加對書上的代碼進(jìn)行研究,充分的理解其中的關(guān)鍵要素!
,六、附錄:關(guān)鍵代碼(給出適當(dāng)注釋,可讀性高) #include
#include
#pragma comment(lib,"WS2_32")
class CInitSock
{
public:
CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
{
// 初始化Winsock
WSADATA wsaData;
WORD sockVersion = MAKEWORD(minorVer, majorVer); if(::WSAStartup(sockVersion, &wsaData) != 0)
{
exit(0);//初始化失敗,退出程序
}
}
~CInitSock()
{
::WSACleanup();//釋放Winsock 資源
}
};
int main(int argc,char **argv)
{
CInitSock initSock;
char szHost[256];
while(printf("輸入域名:"))
{
// 通過域名得到地址信息
scanf("s",&szHost);
if(szHost==0)
{
break;
}
hostent *pHost = ::gethostbyname(szHost);
// 打印出所有IP 地址
in_addr addr;
for(int i = 0; ; i )
{
char *p = pHost->h_addr_list[i];
if(p == NULL) break;
,memcpy(&addr.S_un.S_addr, p, pHost->h_length); char *szIp = ::inet_ntoa(addr);
printf("IP地址:sn", szIp);
}
}
printf("n");
return 0;
}
#include
#include
#include "Iphlpapi.h"
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "WS2_32.lib")
/////////////////////////////////////////
// 全局?jǐn)?shù)據(jù)
u_char g_ucLocalMac[6]; // 本地MAC 地址
DWORD g_dwGatewayIP; // 網(wǎng)關(guān)IP 地址
////////////////////
DWORD g_dwGatewayIP1;
DWORD g_dwLocalIP; // 本地IP 地址
DWORD g_dwMask; // 子網(wǎng)掩碼
char *szAdapterName;
char *szAdapterDescription;
BOOL GetGlobalData()
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
ULONG ulLen = 0;
// 為適配器結(jié)構(gòu)申請內(nèi)存
::GetAdaptersInfo(pAdapterInfo,&ulLen);
pAdapterInfo = (PIP_ADAPTER_INFO)::GlobalAlloc(GPTR, ulLen);
// 取得本地適配器結(jié)構(gòu)信息
if(::GetAdaptersInfo(pAdapterInfo,&ulLen) == ERROR_SUCCESS) {
if(pAdapterInfo != NULL)
{
memcpy(g_ucLocalMac, pAdapterInfo->Address, 6); szAdapterName=pAdapterInfo->AdapterName;
,szAdapterDescription=pAdapterInfo->Description;
g_dwGatewayIP = ::inet_addr(pAdapterInfo->GatewayList.IpAddress.String); g_dwLocalIP = ::inet_addr(pAdapterInfo->IpAddressList.IpAddress.String); g_dwMask = ::inet_addr(pAdapterInfo->IpAddressList.IpMask.String);
g_dwGatewayIP1=::inet_addr(pAdapterInfo->Next->IpAddressList.IpAddress.String); }
}
printf(" n -------------------- 本地主機(jī)信息 -----------------------nn");
in_addr in;
in.S_un.S_addr = g_dwLocalIP;
in_addr in1;
in1.S_un .S_addr =g_dwGatewayIP1;
printf(" IP Address : s n", ::inet_ntoa(in));
in.S_un.S_addr = g_dwMask;
printf(" Subnet Mask : s n", ::inet_ntoa(in));
in.S_un.S_addr = g_dwGatewayIP;
printf(" Default Gateway : s n", ::inet_ntoa(in));
u_char *p = g_ucLocalMac;