地址家族和名字解析
一 IP
网际协议( Internet Protocol, IP)是一种用于互联网的网络协议,已经广为人知。它可广泛用于大多数计算机操作系统上,也可用于大多数局域网L A N(比如办公室小型网络)和广域网WA N(比如说互联网)。从它的设计看来, I P是一个无连接的协议,不能保证数据投递万无一失。两个比它高级的协议( T C P和U D P)用于依赖I P协议的数据通信。
1.TCP
面向连接的通信是通过“传输控制协议”(Transmission Control Protocol, TCP)来完成的。T C P提供两台计算机之间的可靠无错的数据传输。应用程序利用T C P进行通信时,源和目标之间会建立一个虚拟连接。这个连接一旦建立,两台计算机之间就可以把数据当作一个双向字节流进行交换。
2.UDP
无连接通信是通过“用户数据报协议”(User Datagram Protocol, UDP)来完成的。U D P不保障可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。简单地说,如果一个客户机向服务器发送数据,这一数据会立即发出,不管服务器是否已准备接收数据。如果服务器收到了客户机的数据,它不会确认收到与否。数据传输方法采用的是数据报。
T C P和U D P两者都利用I P来进行数据传输,一般称为T C P / I P和U D P / I P。Wi n s o c k通过AF_INET地址家族为I P通信定址,这个地址家族的定义在Winsock 1.h和Winsock 2.h中。
3.定址
客户机需要通过T C P或U D P和服务器通信时,必须指定服务器的I P地址和服务端口号,另外,服务器打算监听接入客户机请求时,也必须指定一个I P地址和一个端口号。Wi n s o c k中,应用通过SOCKADDR_ IN结构来指定I P地址和服务端口信息,该结构的格式如下:
s i n f a m i l y字段必须设为AF_INET,以告知Wi n s o c k我们此时正在使用I P地址家族。
准备使用哪个T C P或U D P通信端口来标识服务器服务这一问题,则由s i n _ p o r t字段定义。在选择端口时,应用必须特别小心,因为有些可用端口号是为“已知的”(即固定的)服务保留的(比如说文件传输协议和超文本传输协议,即F T P和H T T P)。“已知的协议”,即固定协议,采用的端口由“互联网编号分配认证( I A N A)”控制和分配,RFC 1700中说明编号。从本质上说,端口号分为下面这三类:“已知”端口、已注册端口、动态和(或)私用端口。
a.0 ~ 1 0 2 3由I A N A控制,是为固定服务保留的。
b.1 0 2 4 ~ 4 9 1 5 1是I A N A列出来的、已注册的端口,供普通用户的普通用户进程或程序使用。
c.4 9 1 5 2 ~ 6 5 5 3 5是动态和(或)私用端口。
注:普通用户应用应该选择1 0 2 4 ~ 4 9 1 5 1之间的已注册端口,从而避免端口号已被另一个应用或系统服务所用。
S O C K A D D R I N结构的s i n a d d r字段用于把一个I P地址保存为一个4字节的数,它是无符号长整数类型。形如a . b . c . d 。一个有用的、名为i n e t _ a d d r的支持函数,可把一个点式I P地址转换成一个3 2位的无符号长整数。它的定义如下:
unsigned long inet_addr{
const char FAR*cp
};
c p字段是一个空中止字符串,它认可点式表示法的I P地址。注意,这个函数把I P地址当作一个按网络字节顺序排列的3 2位无符号长整数返回.
最后一个字段sin_ zero ,只充当填充项的职责,以使S O C K A D D R_ I N结构和S O C K A D D R结构的长度一样。
注:1.特殊地址:对于特定情况下的套接字行为,有两个特殊I P 地址可对它们产生影响。a.特殊地址INADDR_ANY允许服务器应用监听主机计算机上面每个网络接口上的客户机活动。一般情况下,在该地址绑定套接字和本地接口时,网络应用才利用这个地址来监听连接。如果你有一个多址系统,这个地址就允许一个独立应用接受发自多个接口的回应。 b.特殊地址INADDR_BROADCAST用于在一个I P网络中发送广播U D P数据报。要使用这个特殊地址,需要应用设置套接字选项S O _B R O A D C A S T。
二.套接字的创建
创建一个I P套接字的好处是便于应用能够通过T C P、U D P和I P协议进行通信。如要用T C P协议打开一个I P套接字,需调用带有地址家族A F _ I N E T和套接字类型S O C K _ S T R E A M的s o c k e t函数或W S A S o c k e t函数,并把协议字段设成0,方式如下:
要利用U D P协议打开I P套接字,只须指定套接字类型,用这个指定的套接字类型代替s o c k e t函数中的S O C K S T R E A M和上面的W S A S o c k e t调用。还可以打开一个套接字通过I P直接通信。这是把套接字类型设成S O C K R AW来完成的。
三. 名字解析
Wi n s o c k应用打算通过I P和主机通信时,必须知道这个主机的I P地址。但是IP地址不容易记住,而主机名较容易记,所以Wi n s o c k提供了两个支持函数,它们有助于用户把一个主机名解析成I P地址。
Wi n d o w s套接字g e t h o s t b y n a m e和WSAAsynGetHostByName API函数从主机数据库中取回与指定的主机名对应的主机信息。两个函数均返回一个H O S T E N T结构,格式如下:
struct hostent{
char FAR* h_name;
char FAR* FAR* h_aliases;
short h_addrtype;
short h_length;
char FAR* FAR* h_addr_list;
};
h n a m e字段是正式的主机名。如果网络采用了“域内命名系统”(D N S),它就是导致命名服务器返回响应的“全限定域名”(F Q D N)。如果网络使用一个本地“多主机”文件,主机名就是I P地址之后的第一个条目。h _ a l i a s e s字段是一个由主机备用名组成的空中止数组。h a d d r t y p e表示即将返回的地址家族。h l e n g t h字段则对h a d d r l i s t字段中的每一个地址定义字节长度进行定义。h a d d r l i s t字段是一个由主机I
P地址组成的空中止数组(可以为一个主机分配若干个I P地址)。这个数组中的每个地址都是按网络字节顺序返回的。一般情况下,应用程序都采用该数组中的第一个地址。但是,如果返回的地址不止一个,应用程序就会相应地选择一个最恰当的,而不是一直都用第一个地址.
gethostbyname API函数的定义如下:
struct hostent FAR *gethostname{
const char FAR* name;
};
n a m e参数表示准备查找的那个主机的友好名。如果这个函数调用成功,系统就会返回一个指向H O S T E N T结构的指针。注意,保存H O S T E N T结构的是系统内存。应用程序不应该依靠它来维护状态。由于该内存由系统维护,因此,你的应用程序不必释放这个已返回的结构。
WSAAsyncGetHostByName API函数是g e t h o s t b y n a m e函数的异步版,后一个函数在结束时,利用Wi n d o w s消息向应用程序发出通知。W S A A s y n G e t H o s t B y N a m e的定义如下:
另外两个用于获得主机信息的函数是: g e t h o s t b y a d d r和WSAAsynGetHostByName API函数,它们是为获得与I P网络地址相应的主机信息而设计的。