Windows Socket 1.1库函数参考

来源:互联网 发布:java下载网页源代码 编辑:程序博客网 时间:2024/05/17 09:02
5.1 Windows Socket 1.1库函数参考

本章以字母顺序列出了套接口库函数,并介绍了技术细节。
使用任一库函数时应在程序中包含WINSOCK.H头文件。在附录A.2中还列出了一些与BERKELEY兼容的头文件。这些头文件只起到兼容性的作用,它们都包含了WINSOCK.H头文件,WINDOWS.H头文件也是必需的,但WINSOCK.H会视需要包含这一头文件。

5.1.1 accept()
简述:
在一个套接口接受一个连接。

#include

SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr,
int FAR* addrlen);

s:套接口描述字,该套接口在listen()后监听连接。
addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
addrlen:(可选)指针,指向存有addr地址长度的整形数。

注释:
本函数从s的等待连接队列中抽取第一个连接,创建一个与s同类的新的套接口并返回句柄。如果队列中无等待连接,且套接口为非阻塞方式,则accept()阻塞调用进程直至新的连接出现。如果套接口为非阻塞方式且队列中等待连接,则accept()返回一错误代码。已接受连接的套接口不能用于接受新的连接,原套接口仍保持开放。
addr参数为一个返回参数,其中填写的是为通讯层所知的连接实体地址。addr参数的实际格式由通讯时产生的地址族确定。addrlen参数也是一个返回参数,在调用时初始化为addr所指的地址空间;在调用结束时它包含了实际返回的地址的长度(用字节数表示)。该函数与SOCK_STREAM类型的面向连接的套接口一起使用。如果addr与addrlen中有一个为零NULL,将不返回所接受的套接口远程地址的任何信息。

返回值:
如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值。否则的话,返回INVALID_SOCKET错误,应用程序可通过调用WSAGetLastError()来获得特定的错误代码。
addrlen所指的整形数初始时包含addr所指地址空间的大小,在返回时它包含实际返回地址的字节长度。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:addrlen参数太小(小于socket结构的大小)。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEINVAL:在accept()前未激活listen()。
WSAEMFILE:调用accept()时队列为空,无可用的描述字。
WSAENOBUFS:无可用缓冲区空间。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:该套接口类型不支持面向连接服务。
WSAEWOULDBLOCK:该套接口为非阻塞方式且无连接可供接受。

参见:
bind(), connect(), listen(), select(), socket(), WSAAsyncSelect().


5.1.2 bind()
简述:
将一本地地址与一套接口捆绑。

#include

int PASCAL FAR bind( SOCKET s, const struct sockaddr FAR* name,
int namelen);

s:标识一未捆绑套接口的描述字。
name:赋予套接口的地址。sockaddr结构定义如下:

struct sockaddr{
u_short sa_family;
char sa_data[14];
};

namelen:name名字的长度。

注释:
本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/断口号)。
在Internet地址族中,一个名字包括几个组成部分,对于SOCK_PGRAM和SOCK_STREAM类套接口,名字由三部分组成:主机地址,协议号(显式设置为UDP和TCP)和用以区分应用的端口号。如果一个应用并不关心分配给它的地址,则可将Internet地址设置为INADDR_ANY,或将端口号置为0。如果Internet地址段为INADDR_ANY,则可使用任意网络接口;在有多种主机环境下可简化编程。如果端口号置为0,则WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。应用程序可在bind()后用getsockname()来获知所分配的地址,但必需注意的是,getsockname()只有在套接口连接成功后才会填写Internet地址,这是由于在多种主机环境下若干种Internet地址都是有效的。
如果一个应用程序需要把端口捆绑到超过1024-5000范围的特定端口时,比如rsh需要捆绑到任一保留端口,则可如下编程:

SOCKADDR_IN sin;
SOCKET s;
u_short alport=IPPORT_RESERVED;
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=0;
for (;;) {
sin.sin_port=htons(alport);
if (bind(s,(LPSOCKADDR)&sin, sizeof(sin))=0) {

}
if (GetLastError()!=WSAEADDRINUSE) {

}
alport-;
if (alport=IPPORT_RESERVED/2) {


}
}


返回值:
如无错误发生,则bind()返回0。否则的话,将返回SOCKET_ERROR,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEADDRINUSE:所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。
WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEAFNOSUPPORT:本协议不支持所指定的地址族。
WSAEINVAL:该套接口已与一个地址捆绑。
WSAENOBUFS:无足够可用缓冲区,连接过多。
WSAENOTSOCK:描述字不是一个套接口。

参见:
connect(), listen(), getsockname(), setsockopt(), socket(), WSACancelBlockingCall().


5.1.3 closesocket()
简述:
关闭一个套接口。

#include

int PASCAL FAR closesocket( SOCKET s);

s:一个套接口的描述字。

注释:
本函数关闭一个套接口。更确切地说,它释放套接口描述字s,以后对s的访问均以WSAENOTSOCK错误返回。若本次为对套接口的最后一次访问,则相应的名字信息及数据队列都将被释放。closesocket()的语义受SO_LINGER与SO_DONTLINGER选项影响,对比如下:

选项 间隔 关闭方式 等待关闭与否
SO_DONTLINGER 不关心 优雅 否
SO_LINGER 零 强制 否
SO_LINGER 非零 优雅 是

若设置了SO_LINGER(亦即linger结构中的l_onoff域设为非零,参见2.4,4.1.7和4.1.21各节),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv()调用将以WSAECONNRESET出错。
若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。
若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger结构的l_onoff域设为零;参见2.4,4.1.7,4.1.21节),则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。

返回值:
如无错误发生,则closesocket()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAENOTSOCK:描述字不是一个套接口。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEWOULDBLOCK:该套接口设置为非阻塞方式且SO_LINGER设置为非零超时间隔。

参见:
accept(), socket(), ioctlsocket(), setsockopt(), WSAAsyncSelect().

5.1.4 connect()
简述:
建立与一个端的连接。

#include

int PASCAL FAR connect( SOCKET s, const struct sockaddr FAR* name,
int namelen);

s:标识一个未连接套接口的描述字。
name:欲进行连接的端口名。
namelen:名字长度。

注释:
本函数用于创建与指定外部端口的连接。s参数指定一个未连接的数据报或流类套接口。如套接口未被捆绑,则系统赋给本地关联一个唯一的值,且设置套接口为已捆绑。请注意若名字结构中的地址域为全零的话,则connect()将返回WSAEADDRNOTAVAIL错误。
对于流类套接口(SOCK_STREAM类型),利用名字来与一个远程主机建立连接,一旦套接口调用成功返回,它就能收发数据了。对于数据报类套接口(SOCK_DGRAM类型),则设置成一个缺省的目的地址,并用它来进行后续的send()与recv()调用。

返回值:
若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。对阻塞套接口而言,若返回值为SOCKET_ERROR则应用程序调用WSAGetLsatError()。如果它指出错误代码为WSAEWOULDBLOCK,则您的应用程序可以:
1.用select(),通过检查套接口是否可写,来确定连接请求是否完成。或者,
2.如果您的应用程序使用基于消息的WSAAsynSelect()来表示对连接事件的兴趣,则当连接操作完成后,您会收到一个FD_CONNECT消息。

错误代码:
WSAENOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEADDRINUSE:所指的地址已在使用中。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEADDRNOTAVAIL:在本地机器上找不到所指的地址。
WSAENOTSUPPORT:所指族中地址无法与本套接口一起使用。
WSAECONNREFUSED:连接尝试被强制拒绝。
WSAEDESTADDREQ:需要目的地址。
WSAEFAULT:namelen参数不正确。
WSAEINVAL:套接口没有准备好与一地址捆绑。
WSAEISCONN:套接口早已连接。
WSAEMFILE:无多余文件描述字。
WSAENETUNREACH:当前无法从本主机访问网络。
WSAENOBUFS:无可用缓冲区。套接口未被连接。
WSAENOTSOCK:描述字不是一个套接口。
WSAETIMEOUT:超时时间到。
WSAEWOULDBLOCK:套接口设置为非阻塞方式且连接不能立即建立。可用select()调用对套接口写,因为select()时会进行连接。

参见:
accept(), bind(), getsockname(), socket(), select(), WSAAsyncSelect().


5.1.5 getpeername()
简述:
获取与套接口相连的端地址。

#include

int PASCAL FAR getpeername( SOCKET s, struct sockaddr FAR* name,
int FAR* namelen);

s:标识一已连接套接口的描述字。
name:接收端地址的名字结构。
namelen:一个指向名字结构的指针。

注释:
getpeername()函数用于从端口s中获取与它捆绑的端口名,并把它存放在sockaddr类型的name结构中。它适用于数据报或流类套接口。

返回值:
若无错误发生,getpeername()返回0。否则的话,返回SOCKET_ERROR,应用程序可通过WSAGetLastError()来获取相应的错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:namelen参数不够大。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTCONN 套接口未连接。
WSAENOTSOCK:描述字不是一个套接口。

参见:
bind(), socket(), getsockname().


5.1.6 getsockname()
简述:
获取一个套接口的本地名字。

#include

int PASCAL FAR getsockname( SOCKET s, struct sockaddr FAR* name,
int FAR* namelen);

s:标识一个已捆绑套接口的描述字。
name:接收套接口的地址(名字)。
namelen:名字缓冲区长度。

注释:
getsockname()函数用于获取一个套接口的名字。它用于一个已捆绑或已连接套接口s,本地地址将被返回。本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。
若一个套接口与INADDR_ANY捆绑,也就是说该套接口可以用任意主机的地址,此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息。除非套接口被连接,WINDOWS套接口应用程序不应假设IP地址会从INADDR_ANY变成其他地址。这是因为对于多个主机环境下,除非套接口被连接,否则该套接口所用的IP地址是不可知的。

返回值:
若无错误发生,getsockname()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:namelen参数不够大。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTSOCK:描述字不是一个套接口。
WSAEINVAL:套接口未用bind()捆绑。

参见:
bind(), socket(), getpeername().


5.1.7 getsockopt()
简述:
获取一个套接口选项。

#include

int PASCAL FAR getsockopt( SOCKET s, int level, int optname,
char FAR* optval, int FAR* optlen);

s:一个标识套接口的描述字。
level:选项定义的层次。支持的层次仅有SOL_SOCKET和IPPROTO_TCP。
optname:需获取的套接口选项。
optval:指针,指向存放所获得选项值的缓冲区。
optlen:指针,指向optval缓冲区的长度值。

注释:
getsockopt()函数用于获取任意类型、任意状态套接口的选项当前值,并把结果存入optval。在不同协议层上存在选项,但往往是在最高的“套接口”层次上,设置选项影响套接口的操作,诸如操作的阻塞与否、包的选径方式、带外数据的传送等。
被选中选项的值放在optval缓冲区中。optlen所指向的整形数在初始时包含缓冲区的长度,在调用返回时被置为实际值的长度。对SO_LINGER选项而言,相当于linger结构的大小,对其他选项来说,是一个整形数的大小。
如果未进行setsockopt()调用,则getsockopt()返回系统缺省值。
getsockopt()支持下列选项。其中“类型”栏指出了optval所指向的值。仅有TCP_NODELAY选项使用了IPPROTO_TCP层;其余选项均使用SOL_SOCKET层。

选项 类型 意义
SO_ACCEPTCONN BOOL 套接口正在用listen()监听。
SO_BROADCAST BOOL 套接口设置为传送广播信息。
SO_DEBUG BOOL 允许调试。
SO_DONTLINER BOOL 若为真,则SO_LINGER选项被禁止。
SO_DONTROUTE BOOL 禁止选径。
SO_ERROR int 获取错误状态并清除。
SO_KEEPALIVE BOOL 发送“保持活动”信息。
SO_LINGER struct linger FAR* 返回当前各linger选项。
SO_OOBINLINE BOOL 在普通数据流中接收带外数据。
SO_RCVBUF int 接收缓冲区大小。
SO_REUSEADDR BOOL 套接口能和一个已在使用中的地址捆绑。
SO_SNDBUF int 发送缓冲区大小。
SO_TYPE int 套接口类型(如SOCK_STREAM)。
TCP_NODELAY BOOL 禁止发送合并的Nagle算法。

getsockopt()不支持的BSD选项有:

选项名 类型 意义
SO_RCVLOWAT int 接收低级水印。
SO_RCVTIMEO int 接收超时。
SO_SNDLOWAT int 发送低级水印。
SO_SNDTIMEO int 发送超时。
IP_OPTIONS 获取IP头中选项。
TCP_MAXSEG int 获取TCP最大段的长度。
用一个未被支持的选项去调用getsockopt()将会返回一个WSAENOPROTOOPT错误代码(可用WSAGetLastError()获取)。

返回值:
若无错误发生,getsockopt()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:optlen参数非法。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM类型的套接口不支持SO_ACCEPTCONN、SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。
WSAENOTSOCK:描述字不是一个套接口。

参见:
setsockopt(), WSAAsyncSelect(), socket().

5.1.8 htonl()
简述:
将主机的无符号长整形数转换成网络字节顺序。

#include

u_long PASCAL FAR htonl( u_long hostlong);

hostlong:主机字节顺序表达的32位数。

注释:
本函数将一个32位数从主机字节顺序转换成网络字节顺序。

返回值:
htonl()返回一个网络字节顺序的值。

参见:
htons(), ntohl(), ntohs().


5.1.9 htons()
简述:
将主机的无符号短整形数转换成网络字节顺序。

#include

u_short PASCAL FAR htons( u_short hostshort);

hostshort:主机字节顺序表达的16位数。

注释:
本函数将一个16位数从主机字节顺序转换成网络字节顺序。

返回值:
htons()返回一个网络字节顺序的值。

参见:
htonl(), ntohl(), ntohs().

5.1.10 inet_addr()
简述:将一个点间隔地址转换成一个in_addr。

#include

unsigned long PASCAL FAR inet_addr( const struct FAR* cp);

cp:一个以Internet标准“.”间隔的字符串。

注释:
本函数解释cp参数中的字符串,这个字符串用Internet的“.”间隔格式表示一个数字的Internet地址。返回值可用作Internet地址。所有Internet地址以网络字节顺序返回(字节从左到右排列)。
Internet地址用“.”间隔的地址可有下列几种表达方式:
a.b.c.d,a.b.c,a.b,a
当四个部分都有定值时,每个都解释成一个字节数据,从左到右组成Internet四字节地址。请注意,当一个Internet地址在Intel机器上表示成一个32位整型数时,则上述的字节为“d.c.b.a”。这是因为Intel处理器的字节是从右向左排列的。
请注意:只有Berkeley支持下述表达法,Internet其余各处均不支持。考虑到与软件的兼容性,应按规定进行使用。
对一个三部分地址,最后一部分解释成16位数据并作为网络地址的最右两个字节。这样,三部分地址便很容易表示B组网络地址,如“128.net.host”.
对一个两部分地址,最后一部分解释成24位数据并作为网络地址的最右三个字节,这样,两部分地址便很容易表示C组网络地址,如“net.host”。
对仅有一个部分的地址,则将它的值直接存入网络地址不作任何字节的重组。

返回值:
若无错误发生,inet_addr()返回一个无符号长整型数,其中以适当字节顺序存放Internet地址。如果传入的字符串不是一个合法的Internet地址,如“a.b.c.d”地址中任一项超过255,那么inet_addr()返回INADDR_NONE。

参见:
inet_ntoa().


5.1.11 inet_ntoa()
简述:
将网络地址转换成“.”点隔的字符串格式。

#include

char FAR* PASCAL FAR inet_ntoa( struct in_addr in);

in:一个表示Internet主机地址的结构。

注释:
本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。

返回值:
若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NVLL。其中的数据应在下一个WINDOWS套接口调用前复制出来。

参见:
inet_addr().


5.1.12 ioctlsocket()
简述:
控制套接口的模式。

#include

int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR* argp);

s:一个标识套接口的描述字。
cmd:对套接口s的操作命令。
argp:指向cmd命令所带参数的指针。

注释:
本函数可用于任一状态的任一套接口。它用于获取与套接口相关的操作参数,而与具体协议或通讯子系统无关。支持下列命令:
FIONBIO:允许或禁止套接口s的非阻塞模式。argp指向一个无符号长整型。如允许非阻塞模式则非零,如禁止非阻塞模式则为零。当创建一个套接口时,它就处于阻塞模式(也就是说非阻塞模式被禁止)。这与BSD套接口是一致的。WSAAsynSelect()函数将套接口自动设置为非阻塞模式。如果已对一个套接口进行了WSAAsynSelect() 操作,则任何用ioctlsocket()来把套接口重新设置成阻塞模式的试图将以WSAEINVAL失败。为了把套接口重新设置成阻塞模式,应用程序必须首先用WSAAsynSelect()调用(IEvent参数置为0)来禁至WSAAsynSelect()。
FIONREAD:确定套接口s自动读入的数据量。argp指向一个无符号长整型,其中存有ioctlsocket()的返回值。如果s是SOCKET_STREAM类型,则FIONREAD返回在一次recv()中所接收的所有数据量。这通常与套接口中排队的数据总量相同。如果S是SOCK_DGRAM 型,则FIONREAD返回套接口上排队的第一个数据报大小。
SIOCATMARK:确实是否所有的带外数据都已被读入。这个命令仅适用于SOCK_STREAM类型的套接口,且该套接口已被设置为可以在线接收带外数据(SO_OOBINLINE)。如无带外数据等待读入,则该操作返回TRUE真。否则的话返回FALSE假,下一个recv()或recvfrom()操作将检索“标记”前一些或所有数据。应用程序可用SIOCATMARK操作来确定是否有数据剩下。如果在“紧急”(带外)数据前有常规数据,则按序接收这些数据(请注意,recv()和recvfrom()操作不会在一次调用中混淆常规数据与带外数据)。argp指向一个BOOL型数,ioctlsocket()在其中存入返回值。

兼容性:
本函数为Berkeley套接口函数ioctl()的一个子集。其中没有与FIOASYNC等价的命令,SIOCATMARK是套接口层次支持的唯一命令。

返回值:
成功后,ioctlsocket()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEINVAL:cmd为非法命令,或者argp所指参数不适用于该cmd命令,或者该命令
不适用于此种类型的套接口。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTSOCK:描述字不是一个套接口。

5.1.13 listen()
简述:
创建一个套接口并监听申请的连接.

#include

int PASCAL FAR listen( SOCKET s, int backlog);

S:用于标识一个已捆绑未连接套接口的描述字。
backlog:等待连接队列的最大长度。

注释:
为了接受连接,先用socket()创建一个套接口,然后用listen()为申请进入的连接建立一个后备日志,然后便可用accept()接受连接了。listen()仅适用于支持连接的套接口,如SOCK_STREAM类型的。套接口s处于一种“变动”模式,申请进入的连接请求被确认,并排队等待被接受。这个函数特别适用于同时有多个连接请求的服务器;如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。
当没有可用的描述字时,listen()函数仍试图正常地工作。它仍接受请求直至队列变空。当有可用描述字时,后续的一次listen()或accept()调用会将队列按照当前或最近的“后备日志”重新填充,如有可能的话,将恢复监听申请进入的连接请求。

兼容性:
后备日志当前被(默认地)限制为5。如同4.3 BSD Unix中的一样,小于1或大于5的数都会被舍入最近的有效值。

返回值:
如无错误发生,listen()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEADDRINUSE:试图用listen()去监听一个正在使用中的地址。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEINVAL:该套接口未用bind()进行捆绑,或已被连接。
WSAEISCONN:套接口已被连接。
WSAEMFILE:无可用文件描述字。
WSAENOBUFS:无可用缓冲区空间。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:该套接口不正常listen()调用。

参见:
accept(), connet(), socket().


5.1.14 ntohl()
简述:
将一个无符号长整形数从网络字节顺序转换为主机字节顺序。

#include

u_long PASCAL FAR ntohl( u_long netlong);

netlong:一个以网络字节顺序表达的32位数。

注释:
本函数将一个32位数由网络字节顺序转换为主机字节顺序。

返回值:
ntohl()返回一个以主机字节顺序表达的数。

参见:
htonl(), htons(), ntohs().


5.1.15 ntohs()
简述:
将一个无符号短整形数从网络字节顺序转换为主机字节顺序。

#include

u_short PASCAL FAR ntohs( u_short netshort);

netshort:一个以网络字节顺序表达的16位数。

注释:
本函数将一个16位数由网络字节顺序转换为主机字节顺序。

返回值:
ntohs()返回一个以主机字节顺序表达的数。

参见:
htonl(), htons(), ntohl().


5.1.16 recv()
简述:
从一个套接口接收数据。

#include

int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);

s:一个标识已连接套接口的描述字。
buf:用于接收数据的缓冲区。
len:缓冲区长度。
flags:指定调用方式。

注释:
本函数用于已连接的数据报或流式套接口s进行数据的接收。
对SOCK_STREAM类型的套接口来说,本函数将返回所有可用的信息,最大可达缓冲区的大小。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。
对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recv()函数返回WSAEMSGSIZE错误。如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。
如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recv()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:

值 意义
MSG_PEEK查看当前数据。数据将被复制到缓冲区中,但并不从输入队列中删除。
MSG_OOB 处理带外数据(参见2.2.3节具体讨论)。

返回值:
若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAENOTCONN:套接口未连接。
WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。
WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。
WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。
WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。
WSAEINVAL:套接口未用bind()进行捆绑。
WSAECONNABORTED:由于超时或其他原因,虚电路失效。
WSAECONNRESET:远端强制中止了虚电路。

参见:
recvfrom(), read(), recv(), send(), select(), WSAAsyncSelect(), socket().


5.1.17 recvfrom()
简述:
接收一个数据报并保存源地址。

#include

int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,
struct sockaddr FAR* from, int FAR* fromlen);

s:标识一个已连接套接口的描述字。
buf:接收数据缓冲区。
len:缓冲区长度。
flags:调用操作方式。
from:(可选)指针,指向装有源地址的缓冲区。
fromlen:(可选)指针,指向from缓冲区长度值。

注释:
本函数由于从(已连接)套接口上接收数据,并捕获数据发送源的地址。
对于SOCK_STREAM类型的套接口,最多可接收缓冲区大小个数据。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。对于SOCK_STREAM类型套接口,忽略from和fromlen参数。
对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recvfrom()函数返回WSAEMSGSIZE错误。
若from非零,且套接口为SOCK_DGRAM类型,则发送数据源的地址被复制到相应的sockaddr结构中。fromlen所指向的值初始化时为这个结构的大小,当调用返回时按实际地址所占的空间进行修改。
如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。
如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recvfrom()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。
在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:
值 意义
MSG_PEEK 查看当前数据。数据将被复制到缓冲区中,但并不从输入队列中删除。
MSG_OOB 处理带外数据(参见2.2.3节具体讨论)。

返回值:
若无错误发生,recvfrom()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:fromlen参数非法;from缓冲区大小无法装入端地址。
WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEINVAL:套接口未用bind()进行捆绑。
WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型)。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。
WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。
WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。
WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。
WSAECONNABORTED:由于超时或其他原因,虚电路失效。
WSAECONNRESET:远端强制中止了虚电路。

参见:
recv(), send(), socket(), WSAAsyncSelect().


5.1.18 select()
简述:
确定一个或多个套接口的状态,如需要则等待。

#include

int PASCAL FAR select( int nfds, fd_set FAR* readfds,
fd_set FAR* writefds, fd_set FAR* exceptfds,
const struct tim FAR* timeout);

nfds:本参数忽略,仅起到兼容作用。
readfds:(可选)指针,指向一组等待可读性检查的套接口。
writefds:(可选)指针,指向一组等待可写性检查的套接口。
exceptfds:(可选)指针,指向一组等待错误检查的套接口。
timeout:select()最多等待时间,对阻塞操作则为NULL。

注释:
本函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用fd_set结构来表示一组等待检查的套接口。在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。有一组宏可用于对fd_set的操作,这些宏与Berkeley Unix软件中的兼容,但内部的表达是完全不同的。
readfds参数标识等待可读性检查的套接口。如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成。对其他套接口而言,可读性意味着有排队数据供读取。或者对于SOCK_STREAM类型套接口来说,相对于该套接口的虚套接口已关闭,于是recv()或recvfrom()操作均能无阻塞完成。如果虚电路被“优雅地”中止,则recv()不读取数据立即返回;如果虚电路被强制复位,则recv()将以WSAECONNRESET错误立即返回。如果SO_OOBINLINE选项被设置,则将检查带外数据是否存在(参见setsockopt())。
writefds参数标识等待可写性检查的套接口。如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立。如果套接口并未处于connect()调用中,可写性意味着send()和sendto()调用将无阻塞完成。〔但并未指出这个保证在多长时间内有效,特别是在多线程环境中〕。
exceptfds参数标识等待带外数据存在性或意味错误条件检查的套接口。请注意如果设置了SO_OOBINLINE选项为假FALSE,则只能用这种方法来检查带外数据的存在与否。对于SO_STREAM类型套接口,远端造成的连接中止和KEEPALIVE错误都将被作为意味出错。如果套接口正在进行连接connect()(非阻塞方式),则连接试图的失败将会表现在exceptfds参数中。
如果对readfds、writefds或exceptfds中任一个组类不感兴趣,可将它置为空NULL。
在winsock.h头文件中共定义了四个宏来操作描述字集。FD_SETSIZE变量用于确定一个集合中最多有多少描述字(FD_SETSIZE缺省值为64,可在包含winsock.h前用#define FD_SETSIZE来改变该值)。对于内部表示,fd_set被表示成一个套接口的队列,最后一个有效元素的后续元素为INVAL_SOCKET。宏为:
FD_CLR(s,*set):从集合set中删除描述字s。
FD_ISSET(s,*set):若s为集合中一员,非零;否则为零。
FD_SET(s,*set):向集合添加描述字s。
FD_ZERO(*set):将set初始化为空集NULL。
timeout参数控制select()完成的时间。若timeout参数为空指针,则select()将一直阻塞到有一个描述字满足条件。否则的话,timeout指向一个tim结构,其中指定了select()调用在返回前等待多长时间。如果tim为{0,0},则select()立即返回,这可用于探询所选套接口的状态。如果处于这种状态,则select()调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它。举例来说,阻塞钩子函数不应被调用,且WINDOWS套接口实现不应yield。

返回值:
select()调用返回处于就绪状态并且已经包含在fd_set结构中的描述字总数;如果超时则返回0;否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEINVAL:超时时间值非法。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTSOCK:描述字集合中包含有非套接口的元素。

参见:
WSAAsyncSelect(), accept(), connect(), recv(), recvfrom(), send().


5.1.19 send()
简述:
向一个已连接的套接口发送数据。

#include

int PASCAL FAR send( SOCKET s, const char FAR* buf, int len, int flags);

s:一个用于标识已连接套接口的描述字。
buf:包含待发送数据的缓冲区。
len:缓冲区中数据的长度。
flags:调用执行方式。

注释:
send()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。
请注意成功地完成send()调用并不意味着数据传送到达。
如果传送系统的缓冲区空间不够保存需传送的数据,除非套接口处于非阻塞I/O方式,否则send()将阻塞。对于非阻塞SOCK_STREAM类型的套接口,实际写的数据数目可能在1到所需大小之间,其值取决于本地和远端主机的缓冲区大小。可用select()调用来确定何时能够进一步发送数据。
在相关套接口的选项之上,还可通过标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口的选项也取决于标志位。后者由以下一些值组成:
值 意义
MSG_DONTROUTE 指明数据不选径。一个WINDOWS套接口供应商可以忽略此标志;参见2.4节中关于SO_DONTROUTE的讨论。
MSG_OOB 发送带外数据(仅适用于SO_STREAM;参见2.2.3节)。

返回值:
若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小)。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEFAULT:buf参数不在用户地址空间中的有效位置。
WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。
WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁。
WSAENOTCONN:套接口未被连接。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。
WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数。
WSAEWOULDBLOCK:
WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。
WSAEINVAL:套接口未用bind()捆绑。
WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。
WSAECONNRESET:虚电路被远端复位。

参见:
recv(), recvfrom(), socket(), sendto(), WSAStartup().


5.1.20 sendto()
简述:
向一指定目的地发送数据。

#include

int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags,
const struct sockaddr FAR* to, int tolen);

s:一个标识套接口的描述字。
buf:包含待发送数据的缓冲区。
len:buf缓冲区中数据的长度。
flags:调用方式标志位。
to:(可选)指针,指向目的套接口的地址。
tolen:to所指地址的长度。

注释:
sendto()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。
请注意成功地完成sendto()调用并不意味着数据传送到达。
sendto()函数主要用于SOCK_DGRAM类型套接口向to参数指定端的套接口发送数据报。对于SOCK_STREAM类型套接口,to和tolen参数被忽略;这种情况下sendto()等价于send()。
为了发送广播数据(仅适用于SOCK_DGRAM),in参数所含地址应该把特定的IP地址INADDR_BROADCAST(winsock.h中有定义)和终端地址结合起来构造。通常建议一个广播数据报的大小不要大到以致产生碎片,也就是说数据报的数据部分(包括头)不超过512字节。
如果传送系统的缓冲区空间不够保存需传送的数据,除非套接口处于非阻塞I/O方式,否则sendto()将阻塞。对于非阻塞SOCK_STREAM类型的套接口,实际写的数据数目可能在1到所需大小之间,其值取决于本地和远端主机的缓冲区大小。可用select()调用来确定何时能够进一步发送数据。
在相关套接口的选项之上,还可通过标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口的选项也取决于标志位。后者由以下一些值组成:

值 意义
MSG_DONTROUTE 指明数据不选径。一个WINDOWS套接口供应商可以忽略此标志;参见2.4节中关于SO_DONTROUTE的讨论。
MSG_OOB 发送带外数据(仅适用于SO_STREAM;参见2.2.3节)。

返回值:
若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小)。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEFAULT:buf或to参数不是用户地址空间的一部分,或to参数太小(小于sockaddr结构大小)。
WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。
WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁。
WSAENOTCONN:套接口未被连接。
WSAENOTSOCK:描述字不是一个套接口。
WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。
WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数。
WSAEWOULDBLOCK:套接口被标志为非阻塞, 但该调用会产生阻塞。
WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。
WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。
WSAECONNRESET:虚电路被远端复位。
WSAEADDRNOTAVAIL:所指地址无法从本地主机获得。
WSAEAFNOSUPPORT:所指定地址族中地址无法与本套接口一切使用。
WSAEDESADDRREQ:需要目的地址。
WSAENETUNREACH:当前无法从本主机联上网络。

参见:
recv(), recvfrom(), socket(), send(), WSAStartup().


5.1.21 setsockopt()
简述:
设置套接口的选项。

#include

int PASCAL FAR setsockopt( SOCKET s, int level, int optname,
const char FAR* optval, int optlen);

s:标识一个套接口的描述字。
level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
optname:需设置的选项。
optval:指针,指向存放选项值的缓冲区。
optlen:optval缓冲区的长度。

注释:
setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。
有两种套接口的选项:一种是布尔型选项,允许或禁止一种特性;另一种是整形或结构选项。允许一个布尔型选项,则将optval指向非零整形数;禁止一个选项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其他选项,optval指向包含所需选项的整形数或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,且closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。应用程序通过创建一个linger结构来设置相应的操作特性:
struct linger {
int l_onoff;
int l_linger;
};
为了允许SO_LINGER,应用程序应将l_onoff设为非零,将l_linger设为零或需要的超时值(以秒为单位),然后调用setsockopt()。为了允许SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff应设为零,然后调用setsockopt()。
缺省条件下,一个套接口不能与一个已在使用中的本地地址捆绑(参见bind())。但有时会需要“重用”地址。因为每一个连接都由本地地址和远端地址的组合唯一确定,所以只要远端地址不同,两个套接口与一个地址捆绑并无大碍。为了通知WINDOWS套接口实现不要因为一个地址已被一个套接口使用就不让它与另一个套接口捆绑,应用程序可在bind()调用前先设置SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释;故此无需(但也无害)将一个不会共用地址的套接口设置该选项,或者在bind()对这个或其他套接口无影响情况下设置或清除这一选项。
一个应用程序可以通过打开SO_KEEPALIVE选项,使得WINDOWS套接口实现在TCP连接情况下允许使用“保持活动”包。一个WINDOWS套接口实现并不是必需支持“保持活动”,但是如果支持的话,具体的语义将与实现有关,应遵守RFC1122“Internet主机要求-通讯层”中第4.2.3.6节的规范。如果有关连接由于“保持活动”而失效,则进行中的任何对该套接口的调用都将以WSAENETRESET错误返回,后续的任何调用将以WSAENOTCONN错误返回。
TCP_NODELAY选项禁止Nagle算法。Nagle算法通过将未确认的数据存入缓冲区直到蓄足一个包一起发送的方法,来减少主机发送的零碎小数据包的数目。但对于某些应用来说,这种算法将降低系统性能。所以TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在确切了解它的效果并确实需要的情况下,才设置TCP_NODELAY选项,因为设置后对网络性能有明显的负面影响。TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。
如果设置了SO_DEBUG选项,WINDOWS套接口供应商被鼓励(但不是必需)提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨论范围。
setsockopt()支持下列选项。其中“类型”表明optval所指数据的类型。
选项 类型 意义
SO_BROADCAST BOOL 允许套接口传送广播信息。
SO_DEBUG BOOL 记录调试信息。
SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。
SO_DONTROUTE BOOL 禁止选径;直接传送。
SO_KEEPALIVE BOOL 发送“保持活动”包。
SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。
SO_OOBINLINE BOOL 在常规数据流中接收带外数据。
SO_RCVBUF int 为接收确定缓冲区大小。
SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。
SO_SNDBUF int 指定发送缓冲区大小。
TCP_NODELAY BOOL 禁止发送合并的Nagle算法。

setsockopt()不支持的BSD选项有:
选项名 类型 意义
SO_ACCEPTCONN BOOL 套接口在监听。
SO_ERROR int 获取错误状态并清除。
SO_RCVLOWAT int 接收低级水印。
SO_RCVTIMEO int 接收超时。
SO_SNDLOWAT int 发送低级水印。
SO_SNDTIMEO int 发送超时。
SO_TYPE int 套接口类型。
IP_OPTIONS 在IP头中设置选项。

返回值:
若无错误发生,setsockopt()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEFAULT:optval不是进程地址空间中的一个有效部分。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEINVAL:level值非法,或optval中的信息非法。
WSAENETRESET:当SO_KEEPALIVE设置后连接超时。
WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM类型的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。
WSAENOTCONN:当设置SO_KEEPALIVE后连接被复位。
WSAENOTSOCK:描述字不是一个套接口。

5.1.22 shutdown()
简述:
禁止在一个套接口上进行数据的接收与发送。

#include

int PASCAL FAR shutdown( SOCKET s, int how);

s:用于标识一个套接口的描述字。
how:标志,用于描述禁止哪些操作。

注释:
shutdown()函数用于任何类型的套接口禁止接收、禁止发送或禁止收发。
如果how参数为0,则该套接口上的后续接收操作将被禁止。这对于低层协议无影响。对于TCP协议,TCP窗口不改变并接收前来的数据(但不确认)直至窗口满。对于UDP协议,接收并排队前来的数据。任何情况下都不会产生ICMP错误包。
若how为1,则禁止后续发送操作。对于TCP,将发送FIN。
若how为2,则同时禁止收和发。
请注意shutdown()函数并不关闭套接口,且套接口所占有的资源将被一直保持到closesocket()调用。

评注:
无论SO_LINGER设置与否,shutdown()函数不会阻塞。
一个应用程序不应依赖于重用一个已被shutdown()禁止的套接口。特别地,一个WINDOWS套接口实现不必支持在这样的套接口上使用connect()调用。

返回值:
如果没有错误发生,shutdown()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEINVAL:how参数非法。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型套接口)。
WSAENOTSOCK:描述字不是一个套接口。

参见:
connect(), socket().


5.1.23 socket()
简述:
创建一个套接口。

#include

SOCKET PASCAL FAR socket( int af, int type, int protocol);

af:一个地址描述。目前仅支持PF_INET格式,也就是说ARPA Internet地址格式。
type:新套接口的类型描述。
protocol:套接口所用的协议。如调用者不想指定,可用0。

注释:
socket()函数用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。如果协议protocol未指定(等于0),则使用缺省的连接方式。
对于使用一给定地址族的某一特定套接口,只支持一种协议。但地址族可设为AF_UNSPEC(未指定),这样的话协议参数就要指定了。协议号特定于进行通讯的“通讯域”。支持下述类型描述:

类型 解释
SOCK_STREAM 提供有序的、可靠的、双向的和基于连接的字节流,使用带外数据传送机制,为Internet地址族使用TCP。
SOCK_DGRAM 支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务,为Internet地址族使用UDP。

SOCK_STREAM类型的套接口为全双向的字节流。对于流类套接口,在接收或发送数据前必需处于已连接状态。用connect()调用建立与另一套接口的连接,连接成功后,即可用send()和recv()传送数据。当会话结束后,调用closesocket()。带外数据根据规定用send()和recv()来接收。
实现SOCK_STREAM类型套接口的通讯协议保证数据不会丢失也不会重复。如果终端协议有缓冲区空间,且数据不能在一定时间成功发送,则认为连接中断,其后续的调用也将以WSAETIMEOUT错误返回。
SOCK_DGRAM类型套接口允许使用sendto()和recvfrom()从任意端口发送或接收数据报。如果这样一个套接口用connect()与一个指定端口连接,则可用send()和recv()与该端口进行数据报的发送与接收。

返回值:
若无错误发生,socket()返回引用新套接口的描述字。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEAFNOSUPPORT:不支持指定的地址族。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEMFILE:无可用文件描述字。
WSAENOBUFS:无可用缓冲区,无法创建套接口。
WSAEPROTONOSUPPORT:不支持指定的协议。
WSAEPROTOTYPE:指定的协议不适用于本套接口。
WSAESOCKTNOSUPPORT:本地址族中不支持该类型套接口。

参见:
accept(), bind(), connect(), getsockname(), getsockopt(), setsockopt(), listen(), recv(), recvfrom(), select(), send(), sendto(), shutdown(), ioctlsocket().4.2 数据库例程

5.2 数据库函数
5.2.1 gethostbyaddr()
简述:
返回对应于给定地址的主机信息。

#include

struct hostent FAR *PASCAL FAR gethostbyaddr(const char
FAR * addr, int len, int type);

addr:指向网络字节顺序地址的指针。

len: 地址的长度,在PF_INET类型地址中为4。

type:地址类型,应为PF_INET。

注释:
gethostbyaddr()返回对应于给定地址的包含主机名字和地址信息的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 正规的主机名字(PC)。
h_aliases 一个以空指针结尾的可选主机名队列。
h_addrtype 返回地址的类型,对于Windows Sockets,这个域总是PF_INET。
h_legnth 每个地址的长度(字节数),对应于PF_INET这个域应该为4。
h_addr_list 应该以空指针结尾的主机地址的列表,返回的地址是以网络顺序排列的

为了保证其他旧的软件的兼容性,h_addr_list[0]被定义为宏h_addr。

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

返回值:
如果没有错误发生,gethostbyaddr()返回如上所述的一个指向hostent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSAHOST_NOT_FOUND 没有找到授权应答主机。
WSATRY_AGAIN 没有找到非授权主机,或者SERVERFAIL。
WSANO_RECOVERY 无法恢复的错误,FORMERR,REFUSED,NOTIMP。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetHostByAddr(), gethostbyname()

5.2.2 gethostbyname()
简述:
返回对应于给定主机名的主机信息。

#include

struct hostent FAR *PASCAL FAR gethostbyname(const char
FAR * addr);

name:指向主机名的指针。

注释:
gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针。结构的声明与gethostaddr()中一致。

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

gethostbyname()实现没有必要识别传送给它的IP地址串。对于这样的请求,应该把IP地址串当作一个未知主机名同样处理。如果应用程序有IP地址串需要处理,它应该使用inet_addr()函数把地址串转换为IP地址,然后调用gethostbyaddr()来得到hostent结构。

返回值:
如果没有错误发生,gethostbyname()返回如上所述的一个指向hostent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSAHOST_NOT_FOUND 没有找到授权应答主机。
WSATRY_AGAIN 没有找到非授权主机,或者SERVERFAIL。
WSANO_RECOVERY 无法恢复的错误,FORMERR,REFUSED,NOTIMP。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetHostByName(), gethostbyaddr()

5.2.3 gethostname()
简述:
返回本地主机的标准主机名。

#include

int PASCAL FAR gethostname(char FAR *name, int namelen);

name: 一个指向将要存放主机名的缓冲区指针。

namelen:缓冲区的长度。

注释:
该函数把本地主机名存放入由name参数指定的缓冲区中。返回的主机名是一个以NULL结束的字符串。主机名的形式取决于Windows Sockets实现-它可能是一个简单的主机名,或者是一个域名。然而,返回的名字必定可以在gethostbyname()和WSAAsyncGetHostByName()中使用。

返回值:
如果没有错误发生,gethostname()返回0。否则它返回SOCKET_ERROR。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSAEFAULT 名字长度参数太小。
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。

参见:gethostbyname(), WSAAsyncGetHostByName()

5.2.4 getprotobyname()
简述:
返回对应于给定协议名的相关协议信息。

#include

struct protoent FAR * PASCAL FAR getprotobyname(const char
FAR * name);

name:一个指向协议名的指针。

注释:
getprotobyname()返回对应于给定协议名的包含名字和协议号的protoent结构指针。结构的声明如下:

struct protoent {
char FAR * p_name;
char Far * far * p_aliases;
short p_proto;
};

结构的成员有:
成员 用途
p_name 正规的协议名。
p_aliases 一个以空指针结尾的可选协议名队列。
p_proto 以主机字节顺序排列的协议号

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

返回值:
如果没有错误发生,getprotobyname()返回如上所述的一个指向protoent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSANO_RECOVERY 无法恢复的错误,FORMERR,REFUSED,NOTIMP。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetProtoByName(), getprotobynumber()

5.2.5 getprotobynumber()
简述:
返回对应于给定协议号的相关协议信息。

#include

struct protoent FAR * PASCAL FAR getprotobynumber(int number);

number:一个以主机顺序排列的协议号。

注释:
getprotobynumber()返回对应于给定协议名的包含名字和协议号的protoent结构指针。结构的声明与getprotobyname中的一致。

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

返回值:
如果没有错误发生,getprotobynumber()返回如上所述的一个指向protoent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSANO_RECOVERY 无法恢复的错误,FORMERR,REFUSED,NOTIMP。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetProtoByNumber(), getprotobyname()

5.2.6 getservbyname()
简述:
返回对应于给定服务名和协议名的相关服务信息。

#include

struct servent FAR * PASCAL FAR getservbyname(const char
Far * name, const char FAR *proto);

name: 一个指向服务名的指针。

proto:指向协议名的指针(可选)。如果这个指针为空,getservbyname()返回第一个name与s_name或者某一个s_aliases匹配的服务条目。否则getservbyname()对name和proto都进行匹配。

注释:
getservbyname()返回与给定服务名对应的包含名字和服务号信息的servent结构指针。结构的声明如下:

struct servent {
char FAR * s_name;
char Far * FAR * s_aliases;
short s_port;
char FAR * s_proto;
};

结构的成员有:
成员 用途
s_name 正规的服务名。
s_aliases 一个以空指针结尾的可选服务名队列。
s_port 连接该服务时需要用到的端口号,返回的端口号是以网络字节顺序排列的。
s_proto 连接该服务时用到的协议名。

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

返回值:
如果没有错误发生,getservbyname()返回如上所述的一个指向servent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSAHOST_NOT_FOUND 没有找到授权应答主机。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetServByName(), getservbyport()

5.2.7 getservbyport()
简述:
返回对应于给定端口号和协议名的相关服务信息。

#include

struct servent FAR * PASCAL FAR getservbyport(int port,
const char FAR *proto);

port: 给定的端口号,以网络字节顺序排列。

proto:指向协议名的指针(可选)。如果这个指针为空,getservbyport()返回第一个port与s_port匹配的服务条目。否则getservbyport()对port和proto都进行匹配。

注释:
getservbyport()返回与给定服务名对应的包含名字和服务号信息的servent结构指针。结构的声明与getservbyname()中一致。

返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其他Windows Scokets API调用前,把自己所需的信息拷贝下来。

返回值:
如果没有错误发生,getservbyport()返回如上所述的一个指向servent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

错误代码:
WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()。
WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误。
WSAHOST_NOT_FOUND 没有找到授权应答主机。
WSANO_DATA 有效的名字,但没有关于请求类型的数据记录。
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行。
WSAEINTR 阻塞调用被WSACancelBlockingCall()取消了.

参见: WSAAsyncGetServByPort(), getservbyname()

5.3 Windows扩展函数

5.3.1 WSAAsyncGetHostByAddr()
简述:
获得对应于一个地址的主机信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetHostByAddr ( HWND hWnd,
unsigned int wMsg, const char FAR * addr, int len, int
type, char FAR * buf, int buflen );

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
addr 主机网络地址的指针.主机地址以网络字节次序存储.
len 地址长度.对于PF_INET来说必须为4.
type 地址类型,必须是PF_INET.
buf 接收hostent数据的数据区指针.注意该数据区必须大于hostent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳hostent结构,hostent结构的成员引用的所有数据也要在该区域内.建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是gethostbyaddr()的异步版本,是用来获取对应于一个网络地址的主机名和地址信息.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个hostent结构.为存取该结构中的元素,初始的缓冲区指针应置为hostent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetHostByAddr().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetHostByAddr()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetHostByAddr()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造hostent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN Windows Sockets的实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

5.3.2 WSAAsyncGetHostByName()
简述:
获得对应于一个主机名的主机信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetHostByName ( HWND hWnd,
unsigned int wMsg, const char FAR * name, char FAR * buf,
int buflen );

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
name 指向主机名的指针.
buf 接收hostent数据的数据区指针.注意该数据区必须大于hostent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳hostent结构,hostent结构的成员引用的所有数据也要在该区域内.建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是gethostbyname()的异步版本,是用来获取对应于一个主机名的主机名称和地址信息.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个hostent结构.为存取该结构中的元素,初始的缓冲区指针应置为hostent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetHostByName().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetHostByName()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetHostByName()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造hostent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

参见:
gethostbyname(), WSACancelAsyncRequest()

5.3.3 WSAAsyncGetProtoByName()
简述:
获得对应于一个协议名的协议信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetProtoByName ( HWND hWnd,
unsigned int wMsg, const char FAR * name, char FAR * buf,
int buflen );

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
name 指向要获得的协议名的指针.
buf 接收protoent数据的数据区指针.注意该数据区必须大于protoent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳protoent结构,protoent结构的成员引用的所有数据也要在该区域内. 建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是getprotobyname()的异步版本,是用来获取对应于一个协议名的协议名称和代号.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个protoent结构.为存取该结构中的元素,初始的缓冲区指针应置为protoent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetProtoByName().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetProtoByName()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetProtoByName()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造protoent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

参见:
getprotobyname(), WSACancelAsyncRequest()

5.3.4 WSAAsyncGetProtoByNumber()
简述:
获得对应于一个协议号的协议信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetProtoByNumber ( HWND hWnd,
unsigned int wMsg, int number, char FAR * buf, int buflen);

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
number 要获得的协议号,以主机字节序.
buf 接收protoent数据的数据区指针.注意该数据区必须大于protoent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳protoent结构,protoent结构的成员引用的所有数据也要在该区域内. 建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是getprotobynumber()的异步版本,是用来获取对应于一个协议号的协议名称和代号.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个protoent结构.为存取该结构中的元素,初始的缓冲区指针应置为protoent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetProtoByNumber().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetProtoByNumber()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetProtoByNumber()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造protoent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障. WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

参见:
getprotobynumber(), WSACancelAsyncRequest()

5.3.5 WSAAsyncGetServByName()
简述:
获得对应于一个服务名和接口的服务信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetServByName ( HWND hWnd,
unsigned int wMsg, const char FAR * name, const char FAR *
proto, char FAR * buf, int buflen );

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
name 指向服务名的指针.
proto 指向协议名称的指针.它可能是NULL,在这种情况下,WSAAsyncGetServByName()将搜索第一个服务入口(满足s_name或s_aliases之一和所给的名字匹配.)否则, WSAAsyncGetServByName()将和名和协议同时匹配.
buf 接收protoent数据的数据区指针.注意该数据区必须大于protoent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳protoent结构,protoent结构的成员引用的所有数据也要在该区域内. 建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是getservbyname()的异步版本,是用来获取对应于一个服务名的服务信息.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个hostent结构.为存取该结构中的元素,初始的缓冲区指针应置为hostent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetServByName().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetServByName()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetServByName()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造hostent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

5.3.6 WSAAsyncGetServByPort()
简述:
获得对应于一个服务名和接口的服务信息.-异步版本.
#include

HANDLE PASCAL FAR WSAAsyncGetServByPort ( HWND hWnd,
unsigned int wMsg, int port, const char FAR * proto, char
FAR * buf, int buflen );

hWnd 当异步请求完成时,应该接收消息的窗口句柄.
wMsg 当异步请求完成时,将要接收的消息.
port 服务的接口.以网络字节序.
proto 指向协议名称的指针.它可能是NULL,在这种情况下,WSAAsyncGetServByName()将搜索第一个服务入口(满足s_name或s_aliases之一和所给的名字匹配.)否则, WSAAsyncGetServByName()将和名和协议同时匹配.
buf 接收protoent数据的数据区指针.注意该数据区必须大于protoent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳protoent结构,protoent结构的成员引用的所有数据也要在该区域内. 建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.
buflen 上述数据区的大小.

注释:
本函数是getservbyport()的异步版本,是用来获取对应于一个接口号的服务信息.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.
当异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高16位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个hostent结构.为存取该结构中的元素,初始的缓冲区指针应置为hostent结构的指针,并一如平常地存取.
注意若错误代码为WSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低16位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetServByPort().(也就是大于lParam低16位提供的大小.)
错误代码和缓冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用这些宏可最大地提高应用程序源代码的可移植性.

返回值:
返回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.
若操作成功地初启,WSAAsyncGetServByPort()返回一个HANDLE类型的非0值, 作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.
如果异步操作不能初启,WSAAsyncGetServByPort()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

评价:
Windows Sockets的实现使用提供给该函数的缓冲区来构造hostent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

关于Windows Sockets提供者的说明:
Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

错误代码:
在应用程序的窗口收到消息时可能会设置下列的错误代码.如上所述,它们可以通过WSAGETASYNCERROR宏从应答的消息lParam中取出.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAENOBUFS 可用的缓冲区空间不足或没有.
WSAHOST_NOT_FOUND 未找到授权应答主机.
WSATRY_AGAIN 未找到非授权应答主机,或SERVERFAIL.
WSANO_RECOVERY 不可恢复性错误,FORMERR,REFUSED,NOTIMP.
WSANO_DATA 合法名,无请求类型的数据记录.

下列的错误可能在函数调用时发生,指出异步操作不能初启.
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEWOULDBLOCK 本异步操作此时由于Windows Sockets实现的资源或其它限制的制约而无法调度.

参见:
getservbyport(), WSACancelAsyncRequest()

5.3.7 WSAAsyncSelect()
简述:
通知套接口有请求事件发生.

#include

int PASCAL FAR WSAAsyncSelect ( SOCKET s, HWND hWnd,
unsigned int wMsg, long lEvent );

s 标识一个需要事件通知的套接口的描述符.
hWnd 标识一个在网络事件发生时需要接收消息的窗口句柄.
wMsg 在网络事件发生时要接收的消息.
lEvent 位屏蔽码,用于指明应用程序感兴趣的网络事件集合.

注释:
本函数用来请求Windows Sockets DLL为窗口句柄发一条消息-无论它何时检测到由lEvent参数指明的网络事件.要发送的消息由wMsg参数标明.被通知的套接口由s标识.
本函数自动将套接口设置为非阻塞模式.
lEvent参数由下表中列出的值组成.
值 意义
FD_READ 欲接收读准备好的通知.
FD_WRITE 欲接收写准备好的通知.
FD_OOB 欲接收带边数据到达的通知.
FD_ACCEPT 欲接收将要连接的通知.
FD_CONNECT 欲接收已连接好的通知.
FD_CLOSE 欲接收套接口关闭的通知.

启动一个WSAAsyncSelect()将使为同一个套接口启动的所有先前的WSAAsyncSelect()作废. 例如,要接收读写通知,应用程序必须同时用FD_READ和FD_WRITE调用WSAAsyncSelect(),如下:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
对不同的事件区分不同的消息是不可能的.下面的代码将不会工作;第二个调用将会使第一次调用的作用失效,只有FD_WRITE会通过wMsg2消息通知到.
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);

如果要取消所有的通知,也就是指出Windows Sockets的实现不再在套接口上发送任何和网络事件相关的消息,则lEvent应置为0.
rc = WSAAsyncSelect(s, hWnd, 0, 0);

尽管在本例中,WSAAsyncSelect()立即使传给该套接口的事件消息无效, 仍有可能有消息等在应用程序的消息队列中.应用程序因此也必须仍准备好接收网络消息-即使消息作废.用closesocket()关闭一个套接口也同样使WSAAsyncSelect()发送的消息作废,但在closesocke()之前队列中的消息仍然起作用.
由于一个已调用accept()的套接口和用来接收它的侦听套接口有同样的属性, 任何为侦听套接口设置的的WSAAsyncSelect()事件也同样对已接收的套接口起作用.例如, 如果一个侦听的套接口有WSAAsyncSelect()事件FD_ACCEPT,FD_READ,FD_WRITE, 则任何在那个侦听的套接口上接收的套接口将也有FD_ACCEPT,FD_READ,FD_WRITE事件,以及同样的wMsg的值.若需要不同的wMsg及事件,应用程序应调用WSAAsyncSelect(),将已接收的套接口和想要发送的新消息作为参数传递.
当某一套接口s上发生了一个已命名的网络事件,应用程序窗口hWnd会接收到消息wMsg.wParam参数标识了网络事件发生的套接口.lParam的低字指明了发生的网络事件.lParam的高字则含有一个错误代码.该错误代码可以是winsock.h中定义的任何错误.
错误代码和事件可以通过WSAGETSELECTERRORH和WSAGETSELECTEVENT宏从lParam中取出.定义如下:
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
注意:在accept()调用和为改变事件或wMsg的WSAAsyncSelect()调用中有一个计时窗口.应用程序如果需要给侦听的和调用过accept()的套接口以不同的wMsg,它就应该在侦听的套接口上请求FD_ACCEPT事件,然后在accept()调用后设置相应的事件.由于FD_ACCEPT从不发送给已连接的套接口,而FD_READ,FD_WRITE,FD_OOB及FD_CLOSE也从不发送给侦听套接口,所以不会产生困难.
使用以上的宏将最大限度的提高应用程序的可移植性.
返回的可能网络事件如下:
值 意义
FD_READ 套接口s准备读
FD_WRITE 套接口s准备写
FD_OOB 带外数据准备好在套接口s上读.
FD_ACCEPT 套接口s准备接收新的将要到来的连接.
FD_CONNECT 套接口s上的连接完成.
FD_CLOSE 由套接口s标识的连接已关闭.

返回值:
0 若应用程序感兴趣的网络事件的声明成功.
SOCKET_ERROR 否则.可通过调用WSAGetLastError()返回特定的错误代码.

评价:
尽管WSAAsyncSelect()可以以多个事件的组合来调用,应用程序窗口还是会为每个网络事件接收一条消息.
如同select()函数,WSAAsyncSelect()会被频繁地调用来决定,何时一次数据转移操作(send()或recv())可以启动,并且可以立刻成功.尽管如此,健壮的应用程序必须做好这样的准备, 即它可能接收到消息及启动了一个会立即返回WSAEWOULDBLOCK的WindowsSockets API调用.例如,下列的事件序列是可能的:
(i) 数据到达套接口s;Windows Sockets传递WSAAsyncSelect消息.
(ii) 应用程序处理其它一些消息.
(iii) 在处理过程中,应用程序启动了ioctlsocket(s,FIONREAD...)并且注意到有数据准备好读.
(iv) 应用程序启动recv(s,...)来读数据.
(v) 应用程序循环处理下一条消息,最终到达WSAAsyncSelect消息,表示数据已准备好读.
(vi) 应用程序启动recv(s,...),但失败并有错误WSAEWOULDBLOCK.
其它的事件序列也是可能的.
Windows Sockets DLL不会不断地为某一特定的网络事件向一个应用程序发送消息. 如果已成功地向应用程序窗口发送了一特定事件的通知,对该应用程序窗口将不再为该网络事件发消息,直到应用程序调用函数隐含地重新通知该网络事件.
事件 重新通知函数
FD_READ recv()或recvfrom()
FD_WRITE send()或sendto()
FD_OOB recv()
FD_ACCEPT accept()
FD_CONNECT 无
FD_CLOSE 无
任何对重新通知函数的调用,即使失败,也会达到为相关事件发重新通知消息的效果.
对FD_READ,FD_OOB和FD_ACCEPT事件,消息传递是"水平触发"(level-triggered)的.这意味着,若调用了重新通知函数并且相关的事件对该调用仍有效,WSAAsyncSelect()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列:
(i) Windows Sockets DLL在套接口s上接收100字节的数据并传递一个FD_READ消息.
(ii) 应用程序启动recv(s,buffptr,50,0)接收50字节.
(iii) 由于仍有数据未读,Windows Sockets DLL发送另一个FD_READ消息.

根据以上语义,应用程序不必在收到FD_READ消息时读进所有可读的数据-对应于每一FD_READ消息进行一次recv()调用是恰当的.如果应用程序为一个FD_READ消息而启动了多个recv()调用,它将接收到多个FD_READ消息.这样的应用程序可能希望在开始recv()调用( 通过不为FD_READ事件置位的WSAAsyncSelect()函数调用)之前关闭FD_READ消息.
如果在应用程序初次调用WSAAsyncSelect()或当调用了重新通知函数时,有一个事件为真, 则会发送一个相应的消息.例如,若应用程序调用listen(),就会试图进行连接,然后应用程序调用WSAAsyncSelect()声明它需要为套接口接收FD_ACCEPT消息,WindowsSockets的实现就会立即传递一个FD_ACCEPT消息.
FD_WRITE事件处理起来稍有不同.FD_WRITE消息是在套接口第一次用connect()连接或由accept()接受,并且在send()或sendto()以WSAWOULDBLOCK错误失败后缓冲区空闲时发送的.因此,应用程序可以假设发送可能在第一次FD_WRITE消息时开始,并持续到一次返回WSAEWOULDBLOCK的发送. 在这样的失败后,应用程序将被通知,FD_WRITE消息的发送又将可能.
FD_OOB事件只用在当套接口配置成独立接收带外数据时.如果一个套接口被配置成接收感兴趣的带外数据状态,带外数据将和普通数据等同视之,并且应用程序应该注册它感兴趣的方面,然后将接收FD_READ事件,而不是FD_OOB事件.应用程序可以设置或监控带外数据处理的方法(通过使用setsockopt()或getsockopt()函数,及SO_OOBINLINE选项).
在FD_CLOSE消息中的错误代码指出套接口的关闭是正常的还是异常的.如果错误代码是0,则关闭是正常的;若错误代码是WSAECONNRESET,则套接口的虚套接口将被重置.这些只对SOCK_STREAM类型的套接口起作用.
FD_CLOSE消息在相应套接口的虚电路关闭指令接收到时发送.在TCP术语中,这意味着FD_CLOSE在连接进入了FIN WAIT或CLOSE WAIT状态时发送.这是远端对发送方进行了shutdown()调用或closesocket()调用的结果.
请注意你的应用程序将只会收到FD_CLOSE消息来指出虚电路的关闭.它不会收到FD_READ消息来表示该状况.

错误代码:
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINVAL 指出指定的参数之一是非法的.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
附加的错误代码可能在应用程序窗口接收到消息时被置.这些代码可以用WSAGETSELECTERROR宏从lParam中取出.对应于每个网络事件的可能错误代码为:
事件:FD_CONNECT
WSAEADDRINUSE 给定的地址已被使用.
WSAEADDRNOTAVAIL 指定的地址在本地机器不能使用.
WSAEAFNOSUPPORT 指定族的地址不能和本套接口同时使用.
WSAECONNREFUSED 连接的尝试被拒绝.
WSAEDESTADDRREQ 需要一个目的地址.
WSAEFAULT namelen参数不正确.
WSAEINVAL 套接口已经约束到一个地址.
WSAEISCONN 套接口已经连接.
WSAEMFILE 没有可用的文件描述符.
WSAENETUNREACH 此时网络不能从该主机访问.
WSAENOBUFS 无可用的缓冲区空间.套接口不能连接.
WSAENOTCONN 套接口没有连接.
WSAENOTSOCK 该描述符是文件,不是套接口.
WSAETIMEDOUT 试图连接超时,未建立连接.
事件:FD_CLOSE
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAECONNRESET 连接由远端重建.
WSAECONNABORTED 由于超时或其它失败放弃连接.
事件:FD_READ
事件:FD_WRITE
事件:FD_OOB
事件:FD_ACCEPT
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.

关于Windows Sockets提供者的说明:
Windows Sockets的提供者应确保消息可以成功地传给应用程序.如果PostMessag()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
Windows Sockets提供者应使用WSAMAKESELECTREPLY宏来构造消息中的lParam参数.
当套接口关闭时,Windows Sockets提供者应清除所有保留下来要发送给应用程序窗口的消息.然而应用程序必须准备好接收,放弃任何在closesocket()之前可能已经发送的消息.

参见:
select()

5.3.8 WSACancelAsyncRequest()
简述:
取消一次未完成的异步操作.
#include
int PASCAL FAR WSACancelAsyncRequest(HANDLE hAsyncTackHandle);

hAsyncTaskHandle 指明要取消的异步操作.

注释:
WSACancelAsyncRequest()函数用于取消一次异步操作,该异步操作应是以一个WSAAsyncGetXByY()函数(诸如WSAAsyncGetHostByName())启动的.hAsyncTaskHandle参数标识了要取消的操作,它应由初始函数作为异步任务句柄返回.

返回值:
0 异步操作成功地被取消.
SOCKET_ERROR 其它情况.(同时可通过调用WSAGetLastError()获得错误代码)

评论:
试图取消一个已存在的异步操作WSAAsyncGetXByY()可能失败(错误代码WSAEALREADY),原
因有二:首先,原来的操作已经完成,并且应用程序已经处理了结果消息。其次,原始操作已经完成,但结果消息仍在应用程序窗口队列中等待。

关于Windows Sockets提供者的说明:
应用程序是否能有效地区分WSAEINVAL和WSAEALREADY是不清楚的,因为在这两种情况下,错误代码指出不存在指定句柄的异步操作在运行。(小例外:0总是非法的异步任务句柄。)Windows Sockets规格说明不会规定一个Windows Sockets实现怎样区分这两种情况。最大可能的情况是,WindowsSockets应用程序应将两种错误视为相同。

错误代码:
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINVAL 指出指定的参数之一是非法的.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.
WSAEALREADY 被废除的异步调用已经完成.

参见:
WSAAsyncGetHostByAddr(), WSAAsyncGetHostByName(), WSAAsyncGetProtoByNumber(), WSAAsyncGetProtoByName(), WSAAsyncGetHostByName(), WSAAsyncGetServByPort(), WSAAsyncGetServByName().


5.3.9 WSACancelBlockingCall()
简述:
取消一次正在进行中的阻塞调用。
#include

int PASCAL FAR WSACancelBlockingCall( void );

注释:
本函数取消了任何本任务中尚未完成的阻塞操作。通常用于以下两种情况:
(1)。在一个阻塞调用进行时,应用程序同时在处理接收到的消息。在这种情况下,WSAIsBlocking()返回True.
(2)。一个阻塞调用在进行时,Windows Sockets已经回调了应用程序的“阻塞钩子“函数。(如WSASetBlockingHook())

在每种情况中,原来的阻塞调用将尽快中止,并产生错误码WSAEINTR。(在(1)中,中止发生在Windows消息调度将控制转移到Windows Sockets的阻塞例程中时。在(2)中,阻塞调用将在阻塞钩子函数完成时中止。)
在进行阻塞的connect()操作的情况下,Windows Sockets的实现将尽可能中止阻塞调用,但在连接完成(已经复位)或超时之前,它不可能释放套接口资源。同样值得注意的是在应用程序立即尝试打开一个新的套接口(若没有可用的套接口)或试图连接(connect())同一个套接口时。
取消一个accept()或select()调用不会迫使套接口经过这些调用。只有特殊的调用会失败H魏卧谌∠昂戏ǖ牟僮髟谌∠笠餐戏ǎ捉涌诘淖刺谌魏吻榭鱿露疾换崾苡跋臁*
取消任何除accept()和select()之外的操作可能导致套接口进入非终结的状态.如果一个应用程序取消了一个套接口上的阻塞操作,应用程序唯一可以在套接口上操作的函数调用就是CloseSocket(). 尽管其它一些操作可以在一些WindowsSockets实现上运作。如果一个应用程序想获得最大的可移植性,它必须注意不要在取消操作后依赖于performing operations.应用程序可通过置SO_LINGER上的超时为0来重置连接。
如果一个取消操作损害了SOCK_STREAM的数据流的完整性,Windows Sockets实现必须重建连接并且用WSAECONNABORTED使所有将来的操作(除了closesocket())失败。
返回值:
0 操作成功地被取消。
SOCKET_ERROR 其它。(可通过WSAGetLastError()获得相应错误代码)

评价:
注意网络操作在WSACancelBlockingCall()运行之前完成是可能的。例如,在应用程序处于阻塞钩子中时数据可以在中断时接收到用户缓冲区。在这种情况下,阻塞操作将成功返回如同WSACancelBlockingCall()从未调用过。注意WSACancelBlockingCall()仍是成功的。确认一个操作是否真正地被取消的唯一办法是检查从阻塞调用的WSAEINTR的返回值。

错误代码:
WSANOTINITIALISED 在使用本API前必须进行一次成功的WSAStartup()调用.
WSAENETDOWN WINDOWS SOCKETS实现已检测到网络子系统故障.
WSAEINVAL 指出指定的参数之一是非法的.

5.3.10 WSACleanup()
简述:
中止Windows Sockets DLL的使用.

#include

int PASCAL FAR WSACleanup ( void );

注释:
应用程序或DLL在使用Windows Sockets服务之前必须要进行一次成功的WSAStartup()调用.当它完成了Windows Sockets的使用后,应用程序或DLL必须调用WSACleanup()将其从Windows Sockets的实现中注销,并且该实现释放为应用程序或DLL分配的任何资源.任何打开的并已建立连接的SOCK_STREAM类型套接口在调用WSACleanup()时会重置; 而已经由closesocket()关闭却仍有要发送的悬而未决数据的套接口则不会受影响- 该数据仍要发送.
对应于一个任务进行的每一次WSAStartup()调用,必须有一个WSACleanup()调用.只有最后的WSACleanup()做实际的清除工作;前面的调用仅仅将WindowsSockets DLL中的内置引用计数递减.一个简单的应用程序为确保WSACleanup()调用了足够的次数,可以在一个循环中不断调用WSACleanup()直至返回WSANOTINITIALISED.

返回值:
0 操作成功.
SOCKET_ERROR 否则.同时可以调用WSAGetLastError()获得错误代码.

评价:
一个常见的Windows Sockets编程错误是:试图在一个阻塞钩子函数中调用WSACleanup()并且检测返回值失败.如果在一次阻塞调用正在进行时应用程序需要退出,应用程序必须首先通过调用WSACancelBlockingCall()使该阻塞操作作废, 然后一旦控制返回给应用程序时就启动WSACleanup().

关于Windows Sockets提供者的说明:
良好的Windows Sockets应用程序会通过调用WSACleanup()指出它从Windows Sockets实现中注销.本函数因此可以用来释放分配给指定应用程序的资源.
Windows Sockets的实现必须能处理应用程序在调用WSACleanup()函数之前就中止的情况.-例如,返回一个错误.
在一个多线程的环境下,WSACleanup()中止了Windows Sockets在所有线程上的操作.
Windows Sockets的实现必须确认WSACleanup()调用后,应用程序能调用WSAStartup()函数来重新建立Windows Sockets的应用.

错误代码:
WSANOTINITIALISED 使用本API前必须要进行一次成功的WSAStartup()调用.
WSAENETDOWN Windows Sockets的实现已经检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.


5.3.11 WSAGetLastError()
简述:
获得上次失败操作的错误状态.
#include

int PASCAL FAR WSAGetLastError ( void );

注释:
本函数返回上次发生的网络错误.当一特定的Windows Sockets API函数指出一个错误已经发生,本函数就应调用来获得对应的错误代码.

返回值:
返回值指出了本线程进行的上一次Windows Sockets API函数调用时的错误代码.

关于Windows Sockets提供者的说明:
这里使用WSAGetLastError()函数来获得上一次的错误代码,而不是依靠全局错误变量, 是为了提供和将来的多线程环境相兼容.
注意在一个非占先的Windows环境下,WSAGetLastError()只用来获得Windows Sockets API错误.在占先环境下,WSAGetLastError()将调用GetLastError(), 来获得所有在每线程基础上的Win32 API函数的错误状态.为提高可移植性,应用程序应在调用失败后立即使用WSAGetLastError().
参见:
WSASetLastError()

5.3.12 WSAIsBlocking()
简述:
判断是否有阻塞调用正在进行.

#include

BOOL PASCAL FAR WSAIsBlocking ( void );

注释:
本函数允许任务判断它是否在等待前一次阻塞调用完成时执行.

返回值:
TRUE 如果存在一个尚未完成的阻塞函数在等待完成.
FALSE 否则.

评价:
尽管在阻塞套接口上进行的调用对于应用程序来说似乎"阻塞"着,Windows Sockets DLL必须放弃处理机以使其它应用程序可以使用.这意味着对于启动该阻塞调用的应用程序来说可能会重入-这依赖于它接收的消息.在这种情况下,WSAIsBlocking()函数可用来确定在等待一个未完成的阻塞调用完成时,本任务是否重入.注意WindowsSockets禁止对每一线程多于一个未完成的调用.

关于Windows Sockets提供者的说明:
Windows Sockets的实现必须禁止在每个线程上多于一次的未完成阻塞调用.

5.3.13 WSASetBlockingHook()
简述:
建立一个应用程序指定的阻塞钩子函数.

#include

FARPROC PASCAL FAR WSASetBlockingHook ( FARPROC lpBlockFunc );

lpBlockFunc 指向要安装的阻塞函数的函数指针.

注释:
本函数安装了一个新的函数,由Windows Sockets的实现用来实现阻塞套接口函数调用.
Windows Sockets的实现中包含了一种缺省的机制,通过它可以实现阻塞套接口函数. 函数WSASetBlockingHook()为应用程序提供了在"阻塞"时执行自己的程序,来代替缺省的函数.
当一个应用程序调用了一个阻塞的Windows Sockets API操作时,Windows Sockets的实现启动该操作,然后进入了和下列伪代码相似的循环:

for(;;) {

while(BlockingHook())
;

if(operation_cancelled())
break;

if(operation_complete())
break;
}

注意Windows Sockets的实现可能以不同的次序运行上述代码,例如,对操作完成的检查可能发生在调用阻塞钩子函数之前.缺省的BlockingHook()函数如下:

BOOL DefaultBlockingHook(void) {
MSG msg;
BOOL ret;

ret = (BOOL)PeekMessage(&msg,NULL,0,0,PM_REMOVE);

if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return ret;
}

WSASetBlockingHook()函数用来支持需要更复杂消息处理的应用程序-例如,使用了MDI(多文本界面)的程序.它并不是为运行通常应用程序函数的.特别的,唯一可以由客户阻塞钩子函数调用的唯一WindowsSockets API函数是WSACancelBlockingCall()-它将引起阻塞循环中止.
本函数必须为Windows的非多线程版本和多线程版本(如Windows NT)提供每线程基础上的实现.这样, 它为特殊的任务或线程提供了不影响其它任务或线程的基础上替换阻塞机制的能力.
在Windows的多线程版本中没有缺省的阻塞钩子函数-阻塞调用阻塞了进行该调用的线程.然而, 应用程序可以通过调用WSASetBlockingHook()安装一个特定的阻塞钩子.这为依赖于阻塞钩子的应用程序提供了简单的可移植性.

返回值:
返回值是一个指向前面安装的阻塞函数例程的指针.调用WSASetBlockingHook()函数的应用程序或库应该保留返回值,以使它在需要时能恢复.(若"嵌套"并不重要,应用程序可以简单地放弃WSASetBlockingHook()返回值,并且最终使用WSAUnhookBlockingHook()来恢复缺省的机制.)如果操作失败, 返回一个NULL指针,并且可通过调用WSAGetLastError()获得特定的错误代码.

错误代码:
WSANOTINITIALISED 使用本API前必须要进行一次成功的WSAStartup()调用.
WSAENETDOWN Windows Sockets的实现已经检测到网络子系统故障.
WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行.

参见:
WSAUnhookBlockingHook()

5.3.14 WSASetLastError()
简述:
设置可以被WSAGetLastError()接收的错误代码.

#include

void PASCAL FAR WSASetLastError ( int iError );

iError 指明将被后续的WSAGetLastError()调用返回的错误代码.

注释:
本函数允许应用程序为当前线程设置错误代码,并可由后来的WSAGetLastError()调用返回. 注意任何由应用程序调用的后续Windows Sockets函数都将覆盖本函数设置的错误代码.

关于Windows Sockets提供者的说明:
在Win32环境中,本函数将调用SetLastError().

返回值:
无.

错误代码:
WSANOTINITIALISED 使用本API前必须要进行一次成功的WSAStartup()调用.

参见:
WSAGetLastError()

5.3.15 WSAStartup()
简述:

#include

int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );

wVersionRequested Windows Sockets API提供的调用方可使用的最高版本号.高位字节指出副版本(修正)号,低位字节指明主版本号.
lpWSAData 指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节.

注释:
本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节.应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的WindowsSockets API函数.
为支持日后可能和Windows Sockets 1.1有功能上差异的Windows Sockets实现及应用程序,在WSAStartup()中规定了一个协议.WSAStartup()的调用方和Windows Sockets DLL互相通知对方它们可以支持的最高版本,并且互相确认对方的最高版本是可接受的. 在WSAStartup()函数的入口,Windows Sockets DLL检查了应用程序所需的版本.如果版本高于DLL支持的最低版本,则调用成功并且DLL在wHighVersion中返回它所支持的最高版本,在wVersion中返回它的高版本和wVersionRequested中的较小者.然后Windows Sockets DLL就会假设应用程序将使用wVersion.如果WSDATA结构中的wVersion域对调用方来说不可接收, 它就应调用WSACleanup()函数并且要么去另一个WindowsSockets DLL中搜索,要么初始化失败.
本协议允许Windows Sockets DLL和Windows Sockets应用程序共同支持一定范围的Windows Sockets版本.如果版本范围有重叠,应用程序就可以成功地使用Windows Sockets DLL.下列的图表给出了WSAStartup()在不同的应用程序和WindowsSockets DLL版本中是如何工作的:

应用程序版本 DLL版本 wVersionRequested wVersion wHighVersion 最终结果
1.1 1.1 1.1 1.1 1.1 use 1.1
1.0 1.1 1.0 1.1 1.0 1.0 use 1.0
1.0 1.0 1.1 1.0 1.0 1.1 use 1.0
1.1 1.0 1.1 1.1 1.1 1.1 use 1.1
1.1 1.0 1.1 1.0 1.0 失败
1.0 1.1 1.0 -- -- WSAVERNOTSUPPORTED
1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1
1.1 2.0 1.1 2.0 1.1 1.1 use 1.1
2.0 1.1 2.0 1.1 1.1 失败

下列代码段给出了只支持Windows Sockets 1.1版本的应用程序是如何进行WSAStartup()调用的:

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {


return;
}







if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {


WSACleanup( );
return;
}



下面的代码段示例了只支持1.1版的Windows Sockets DLL是如何进行WSAStartup()协商的:





if ( LOBYTE( wVersionRequested ) < 1 ||
( LOBYTE( wVersionRequested ) == 1 &&
HIBYTE( wVersionRequested ) < 1 ) {
return WSAVERNOTSUPPORTED;
}




lpWsaData->wVersion = MAKEWORD( 1, 1 );
lpWsaData->wHighVersion = MAKEWORD( 1, 1 );

一旦应用程序或DLL进行了一次成功的WSAStartup()调用,它就可以继续进行其它所需的Windows Sockets API调用.当它完成了使用该Windows Sockets DLL的服务后,应用程序或DLL必须调用WSACleanup()以允许WindowsSockets DLL释放任何该应用程序的资源.
实际的Windows Sockets实现细节在WSAData结构中描述如下:

struct WSAData {
WORD wVersion;
WORD wHighVersion;
char
szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
};

该结构的成员为:
成员 用法
wVersion Windows Sockets DLL期待调用方使用的Windows Sockets规范的版本.
wHighVersion DLL可支持的Windows Sockets规范的最高版本.通常它和wVersion相同.
szDescription 一个null结尾的ASCII字串,Windows Sockets DLL将Windows Sockets实现的说明及厂商描述拷至该串.这段文本(长度最多256个字符)可能包含任何字符, 但厂家注意到不把控制和格式字符包含进去:该字串的最可能用法就是在状态消息中显示.
szSystemStatus 一个null结尾的ASCII字串,Windows Sockets DLL将相关的状态和配置信息拷至该串.Windows Sockets DLL只有在该信息对用户或支撑人员有用时才会使用该域:它不应该被认为是szDescription域的扩展.
iMaxSockets 一个进程可以打开的最大套接口数目.Windows Sockets的实现可以提供一个全局的套接口池给任何进程分配;也可以为每个进程分配套接口资源.该数字可反映出Windows Sockets DLL或网络软件是如何配置的.应用程序员可以使用该数字作为该Windows Sockets实现是否可以被应用程序使用的原始依据.例如,一个X Windows服务器可能在它启动时检查iMaxSockets:若它小于8,应用程序应显示一条错误信息, 让用户重新配置网络软件.(这是szSystemStatus可能使用到的一种情况.)显然,并不保证一个特定的应用程序可以实际分配到iMaxSockets个套接口,因为可能有其它的WindowsSockets应用程序在使用.
iMaxUdpDg 以字节表示的可由Windows Sockets应用程序发送或接收的最大UDP数据报的大小.如果应用程序没有给出限制,iMaxUdpDg为0.在Berkeley套接口的许多实现中,对于UDP数据报的导向有一个隐含的限制8192字节.Windows Sockets的实现可以在分配碎片重组缓冲区的基础上给出界限.对于一般的Windows Sockets实现iMaxUdpDg的最小值为512.注意不考虑iMaxUdpDg的值,而试图在网络上发送一个大于最大传输单元(MTU)的广播数据报是不明智的.(WindowsSockets API没有提供发现MTU的机制,但它必须不小于512字节.)
lpVendorInfo 指向厂商规定数据结构的远指针.该结构的定义(如果提供)超出了本规范的范围.

应用程序或DLL若需要多次得到WSAData结构信息,就必须多次调用WSAStartup().然而,wVersionRequired参数假设在所有调用WSAStartup()中都相同;也就是,应用程序或DLL不能在第一次调用WSAStartup()后改变WindowsSockets的版本号.
对应于每一次WSAStartup()调用必须有一个WSACleanup()调用,以使第三级(third-party)DLL可以利用和应用程序相关的Windows Sockets DLL.这意味着,例如,如果应用程序调用了WSAStartup()三次,它就必须调用WSACleanup()三次.对WSACleanup()的前两次调用除了减少内置计数器以外不做任何事, 对任务的最后一次WSACleanup()调用为任务释放了所有所需的资源.

返回值:
0 成功.
否则返回下列的错误代码之一.注意通常依靠应用程序调用WSAGetLastError()机制获得的错误代码是不能使用的,因为Windows Sockets DLL可能没有建立"上一错误"信息储存的客户数据区域.

关于Windows Sockets提供者的说明:
每一个Windows Sockets应用程序必须在进行其它Windows Sockets API调用前进行WSAStartup()调用.这样,本函数就可以用于初始化的目的.
进一步的说明在WSACleanup()的说明中有讨论.

错误代码:
WSASYSNOTREADY 指出网络通信依赖的网络子系统还没有准备好.
WSAVERNOTSUPPORTED 所需的Windows Sockets API的版本未由特定的Windows Sockets实现提供.
WSAEINVAL 应用程序指出的Windows Sockets版本不被该DLL支持.

参见:
send(), sendto(), WSACleanup()

5.3.16 WSAUnhookBlockingHook()
简述:
恢复缺省的阻塞钩子函数.

#include

int PASCAL FAR WSAUnhookBlockingHook ( void );

注释:
本函数除去了任何先前安装的阻塞钩子函数,并且重新安装缺省的阻塞钩子函数.
WSAUnhookBlockingHook()将肯定安装缺省的钩子函数,而非上一个.如果应用程序希望嵌套钩子函数-也就是,建立一个临时的钩子函数,然后返回前一个钩子函数(不论是缺省的还是由前面的WSASetBlockingHook()建立的)-它必须储存和恢复WSASetBlockingHook()的返回值;不能使用WSAUnhookBlockingHook().
在Windows的多线程版本(如Windows NT)中没有缺省的阻塞钩子函数.调用WSAUnhookBlockingHook()去除了应用程序和任何阻塞调用(阻塞了进行该调用的线程本身)安装的所有阻塞钩子函数.

返回值:
0 操作成功.
SOCKET_ERROR 否则.同时可以调用WSAGetLastError()获得错误代码.
抄书
错误代码:
WSANOTINITIALISED 使用本API前必须要进行一次成功的WSAStartup()调用.