在编写程序时,有事需要获取计算机的名字、IP地址以及网络服务或是网络协议相关信息,WinSock提供了一系列函数来帮助应用程序完成相应的信息查询操作。
主机名字与IP地址查询
1.gethostname()
功能:该函数用于查询本地计算机主机的名字。
原型:int gethostname(char *name,int namelen);
参数:
name:指向用于存放主机名字的缓冲区,就是一个字符数组。
namelen:是缓冲区的大小,也就是字符数组name的大小。
若函数调用成功则返回0。
2.gethostbyname()
功能:该函数可根据主机名字查询主机的IP地址等信息,该查询操作就是通常所谓的”域名解析”。
原型:struct hostent *gethostbyname(const char *name);
参数:name指向主机的名字的字符指针(字符串),该名字除了可以是本机的名字外,还可以是网上任一台主机的域名(DNS)。
函数调用成功,则返回一个指向hostent结构指针。
struct hostent{
char *h_name; //主机的规范名
char **h_aliases; //指向主机的别名列表
int h_addrtype; //主机IP地址类型(AF_INET表示IPv4)
int h_length; //主机IP地址长度(4)
char **h_addr_list; //主机IP地址列表(网络字节顺序);
}
程序例子:
#include "WinSock2.h" //包含WinSock库头文件
#include <iostream>
#pragma comment(lib,"ws2_32.lib") //链接WinSock导入库
using namespace std;
int main(){
struct hostent *hptr;
char **pptr;
char hostname[256]; //用于存放获取本机名称或输入的远程主机域名
//加载WinSock DLL
WSADATA wsaData;
WORD wVersionRequested=MAKEWORD(2,2);
if(WSAStartup(wVersionRequested,&wsaData)!=0){
cout<<"加载WinSock DLL失败!"<<endl;
return 0;
}
if(gethostname(hostname,sizeof(hostname))){ //获取本机名字
cout<<"获取主机名字失败!"<<endl;
WSACleanup();
return 0;
}
cout<<"本机名字为:"<<hostname<<endl;
if((hptr=gethostbyname(hostname))==NULL){ //获取本机IP地址
cout<<"通过主机名获取本机IP地址失败!"<<endl;
WSACleanup();
return 0;
}
//输出IP地址
pptr=hptr->h_addr_list;
cout<<"本机IP地址:"<<endl;
while(*pptr!=NULL){ //循环是因为一个主机可能存在多个IP地址
cout<<inet_ntoa(*(struct in_addr *)(*pptr))<<endl; //(struct in_addr *)为强制类型转换
pptr++;
}
//从键盘中输入要解析的网站域名
cout<<"输入要解析的域名:"<<endl;
cin>>hostname;
if((hptr=gethostbyname(hostname))==NULL){ //解析输入的网站域名
cout<<"名字解析失败!"<<endl;
WSACleanup();
return 0;
}
//输出远程主机IP地址
pptr=hptr->h_addr_list;
cout<<"主机IP地址:"<<endl;
while(*pptr!=NULL){ //(struct in_addr *)为强制类型转换
cout<<inet_ntoa(*(struct in_addr *)(*pptr))<<endl;
pptr++;
}
WSACleanup();
system("pause");
}
服务查询
服务器通常都能提供多种不同的服务,比如Web服务,FTP文件服务,Telnet虚拟终端等,每种服务都要使用TCP或者是UDP协议在一个知名的端口号上侦听客户发来的服务请求。WinSock提供了一组函数可以查询本机上所提供的服务、协议以及端口号,程序中可以使用这些函数来获取得服务对应的端口,或者是正在使用指定端口的服务。
1.getservbyname
功能:该函数根据给定的服务名和所使用的协议名获取服务的端口号等信息。
原型:struct servent * getservbyname(const char * name,const char * proto);
参数:
name:指向服务名的指针。
proto:指向协议名的指针(可选,可以为空)。
函数调用成功将返回一个指向servent的结构指针:
struct servent{
char * s_name; //服务名
char ** s_aliases; //一个以空指针结尾的服务别名队列
Short s_port; //连接该服务所需的端口号,以网络字节顺序排列
char * s_proto; //连接该服务所用的传输协议名,通常是TCP或者是UDP
}
2.getservbyport
功能:该函数根据给定的协议和端口号查询服务名称等信息。
原型:struct servent * getservbyport(int port,const char * proto);
参数:
port:给定的端口号,以网络字节顺序排列。
proto:指向传输协议名的指针,可以为空指针。
程序例子:显示本机上所有使用TCP协议的服务的名称和端口号
#include "WinSock2.h" //包含WinSock库头文件
#include <iostream>
#pragma comment(lib,"ws2_32.lib") //链接WinSock导入库
using namespace std;
int main(){
//加载WinSock DLL
WSADATA wsaData;
WORD wVersionRequested=MAKEWORD(2,2);
if(WSAStartup(wVersionRequested,&wsaData)!=0){
cout<<"加载WinSock DLL失败!"<<endl;
return 0;
}
struct servent * pServer;
for(int i=1;i<65535;i++){
pServer=getservbyport(htons(i),"TCP"); //获取服务信息
if(pServer!=NULL){
cout<<"服务名:"<<pServer->s_name<<endl;
cout<<"协议:"<<pServer->s_proto<<endl;
cout<<"端口号:"<<ntohs(pServer->s_port)<<endl;
}
}
WSACleanup(); //注销WinSock DLL
system("pause");
}
协议查询
因特网的每一个协议都有一个正式的名字,比如IP、ICMP、TCP等,在网络内部,协议并不是使用它们的名字标识,而是使用分配给它们的一个唯一号来表示,比如IP编号为0,ICMP编号为1,TCP编号为6等。协议名字主要是为了便于人们阅读,而协议的编号则有利于计算机处理,WinSock提供了两个函数getprotobyname()和getprotobynember()来帮助程序完成协议名字和编号之间的转换。
1.getprotobyname()
功能:根据协议名字查询相应的协议编号等信息。
原型:struct protoent * getprotobyname(const char * name);
函数调用成功,返回一个指向proto结构的指针:
struct protoent{
char p_name; //整个协议名
char **p_aliases; //一个以空指针结尾的可选协议名队列
short p_proto; //主机字节顺序的协议号
}
2.getprotobynumber()
功能:根据协议编号查询协议名字等信息。
原型:struct protoent * getprotobynumber(int number);
程序例子:显示因特网所有协议的名称和相应的协议号
#include "WinSock2.h" //包含WinSock库头文件
#include <iostream>
#pragma comment(lib,"ws2_32.lib") //链接WinSock导入库
using namespace std;
int main(){
//加载WinSock DLL
WSADATA wsaData;
WORD wVersionRequested=MAKEWORD(2,2);
if(WSAStartup(wVersionRequested,&wsaData)!=0){
cout<<"加载WinSock DLL失败!"<<endl;
return 0;
}
struct protoent * pProto;
for(int i=1;i<=256;i++){
if((pProto=getprotobynumber(i))!=NULL){
cout<<"协议名:"<<pProto->p_name<<endl;
cout<<"协议号:"<<pProto->p_proto<<endl;
}
}
WSACleanup(); //注销WinSock DLL
system("pause");
}