第五章 套接口库函数参考

Windows Socket 1.1 库函数参考

本章以字母顺序列出了套接口库函数,并介绍了技术细节。

使用任一库函数时应在程序中包含 WINSOCK.H 头文件。在附录 A.2 中还列出了一些与 BERKELEY 兼容的头文件。这些头文件只起到兼容性的作用,它们都包含了 WINSOCK.H 头文件,WINDOWS.H 头文件也是必需的,但 WINSOCK.H 会视需要包含这一头文件。

accept()

简述:

在一个套接口接受一个连接。#include <winsock.h>

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().

bind()

简述:

将一本地地址与一套接口捆绑。#include <winsock.h>

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) {

/* it worked */

}

if (GetLastError()!=WSAEADDRINUSE) {

/* fail */

}

alport-;

if (alport=IPPORT_RESERVED/2) {

/* fail-all unassigned reserved ports are */

/* in use. */

}

}

返回值:

如无错误发生,则 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().

closesocket()

简述:

关闭一个套接口。#include <winsock.h>

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().

connect()

简述:

建立与一个端的连接。#include <winsock.h>

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().

getpeername()

简述:

获取与套接口相连的端地址。#include <winsock.h>

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().

getsockname()

简述:

获取一个套接口的本地名字。#include <winsock.h>

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().

getsockopt()

简述:

获取一个套接口选项。#include <winsock.h>

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().

htonl()

简述:

将主机的无符号长整形数转换成网络字节顺序。#include <winsock.h>

u_long PASCAL FAR htonl( u_long hostlong); hostlong:主机字节顺序表达的 32 位数。

注释:

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

返回值:

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

参见:

htons(), ntohl(), ntohs().

htons()

简述:

将主机的无符号短整形数转换成网络字节顺序。#include <winsock.h>

u_short PASCAL FAR htons( u_short hostshort); hostshort:主机字节顺序表达的 16 位数。

注释:

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

返回值:

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

参见:

htonl(), ntohl(), ntohs().

inet_addr()

简述:将一个点间隔地址转换成一个 in_addr。#include <winsock.h>

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().

inet_ntoa()

简述:

将网络地址转换成“.”点隔的字符串格式。#include <winsock.h>

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().

ioctlsocket()

简述:

控制套接口的模式。#include <winsock.h>

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:描述字不是一个套接口。

参见:

socket(), setsockopt(), getsockopt(), WSAAsyncSelect().

listen()

简述:

创建一个套接口并监听申请的连接. #include <winsock.h>

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().

ntohl()

简述:

将一个无符号长整形数从网络字节顺序转换为主机字节顺序。

#include <winsock.h>

u_long PASCAL FAR ntohl( u_long netlong); netlong:一个以网络字节顺序表达的 32 位数。

注释:

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

返回值:

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

参见:

htonl(), htons(), ntohs().

ntohs()

简述:

将一个无符号短整形数从网络字节顺序转换为主机字节顺序。

#include <winsock.h>

u_short PASCAL FAR ntohs( u_short netshort); netshort:一个以网络字节顺序表达的 16 位数。

注释:

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

返回值:

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

参见:

htonl(), htons(), ntohl().

recv()

简述:

从一个套接口接收数据。#include <winsock.h>

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().

recvfrom()

简述:

接收一个数据报并保存源地址。#include <winsock.h>

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().

select()

简述:

确定一个或多个套接口的状态,如需要则等待。#include <winsock.h>

int PASCAL FAR select( int nfds, fd_set FAR* readfds, fd_set FAR* writefds, fd_set FAR* exceptfds,

const struct timeval 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 指向一个 timeval 结构,其中指定了 select()调用在返回前等待多长时间。如果 timeval 为{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().

send()

简述:

向一个已连接的套接口发送数据。#include <winsock.h>

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().

sendto()

简述:

向一指定目的地发送数据。#include <winsock.h>

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().

setsockopt()

简述:

设置套接口的选项。#include <winsock.h>

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:描述字不是一个套接口。

参见:

bind(), getsockopt(), ioctlsocket(), socket(), WSAAsyncSelect().

shutdown()

简述:

禁止在一个套接口上进行数据的接收与发送。#include <winsock.h>

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().

socket()

简述:

创建一个套接口。#include <winsock.h>

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 数据库例程

  1. 数据库函数

    1. gethostbyaddr()

简述:

返回对应于给定地址的主机信息。#include <winsock.h>

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()

gethostbyname()

简述:

返回对应于给定主机名的主机信息。#include <winsock.h>

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()

gethostname()

简述:

返回本地主机的标准主机名。#include <winsock.h>

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()

getprotobyname()

简述:

返回对应于给定协议名的相关协议信息。#include <winsock.h>

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()

getprotobynumber()

简述:

返回对应于给定协议号的相关协议信息。#include <winsock.h>

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()

getservbyname()

简述:

返回对应于给定服务名和协议名的相关服务信息。#include <windows.h>

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()

getservbyport()

简述:

返回对应于给定端口号和协议名的相关服务信息。#include <windows.h>

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()

  1. Windows 扩展函数

    1. WSAAsyncGetHostByAddr()

简述:

获得对应于一个地址的主机信息.-异步版本. #include <winsock.h>

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 实现的资源或其它限制的制约而无法调度.

参见:

gethostbyaddr(), WSACancelAsyncRequest()

WSAAsyncGetHostByName()

简述:

获得对应于一个主机名的主机信息.-异步版本. #include <winsock.h>

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()

WSAAsyncGetProtoByName()

简述:

获得对应于一个协议名的协议信息.-异步版本. #include <winsock.h>

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()

WSAAsyncGetProtoByNumber()

简述:

获得对应于一个协议号的协议信息.-异步版本. #include <winsock.h>

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()

WSAAsyncGetServByName()

简述:

获得对应于一个服务名和接口的服务信息.-异步版本. #include <winsock.h>

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 实现的资源或其它限制的制约而无法调度.

参见:

getservbyname(), WSACancelAsyncRequest()

WSAAsyncGetServByPort()

简述:

获得对应于一个服务名和接口的服务信息.-异步版本. #include <winsock.h>

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()

WSAAsyncSelect()

简述:

通知套接口有请求事件发生. #include <winsock.h>

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 的 Windows Sockets API 调用.例如,下列的事件序列是可能的:

  1. 数据到达套接口 s;Windows Sockets 传递 WSAAsyncSelect 消息.

  2. 应用程序处理其它一些消息.

  3. 在处理过程中,应用程序启动了

    ioctlsocket(s,FIONREAD...)并且注意到有数据准备好读.

  4. 应用程序启动 recv(s,...)来读数据.

  5. 应用程序循环处理下一条消息,最终到达 WSAAsyncSelect

    消息,表示数据已准备好读.

  6. 应用程序启动 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()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列:

  1. Windows Sockets DLL 在套接口 s 上接收 100 字节的数据并传递一个FD_READ 消息.

  2. 应用程序启动 recv(s,buffptr,50,0)接收 50 字节.

  3. 由于仍有数据未读,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 消息,Windows Sockets 的实现就会立即传递一个 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()

WSACancelAsyncRequest()

简述:

取消一次未完成的异步操作. #include <winsock.h>

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 实现怎样区分这两种情况。最大可能的情况是,Windows Sockets 应用程序应将两种错误视为相同。

错误代码:

WSANOTINITIALISED 在使用本 API 前必须进行一次成功的WSAStartup()调用.

WSAENETDOWN WINDOWS SOCKETS 实现已检测到网络子系统故障. WSAEINVAL 指出指定的参数之一是非法的.

WSAEINPROGRESS 一个阻塞的 Windows Sockets 操作正在进行. WSAEALREADY 被废除的异步调用已经完成.

参见:

WSAAsyncGetHostByAddr(), WSAAsyncGetHostByName(), WSAAsyncGetProtoByNumber(), WSAAsyncGetProtoByName(), WSAAsyncGetHostByName(), WSAAsyncGetServByPort(), WSAAsyncGetServByName().

WSACancelBlockingCall()

简述:

取消一次正在进行中的阻塞调用。#include <winsock.h>

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(). 尽管其它一些操作可以在一些Windows Sockets 实现上运作。如果一个应用程序想获得最大的可移植性,它必须注意不要在取消操作后依赖于 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 指出指定的参数之一是非法的.

WSACleanup()

简述:

中止 Windows Sockets DLL 的使用. #include <winsock.h>

int PASCAL FAR WSACleanup ( void );

注释:

应用程序或 DLL 在使用 Windows Sockets 服务之前必须要进行一次成功的WSAStartup()调用.当它完成了 Windows Sockets 的使用后,应用程序或 DLL 必须调用 WSACleanup()将其从 Windows Sockets 的实现中注销,并且该实现释放为应用程序或 DLL 分配的任何资源.任何打开的并已建立连接的 SOCK_STREAM 类型套接口在调用WSACleanup()时会重置; 而已经由closesocket()关闭却仍有要发送的悬而未决数据的套接口则不会受影响- 该数据仍要发送.

对应于一个任务进行的每一次 WSAStartup()调用,必须有一个WSACleanup()调用.只有最后的 WSACleanup()做实际的清除工作;前面的调用仅仅将 Windows Sockets 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 操作正在

进行.

参见:

WSAStartup()

WSAGetLastError()

简述:

获得上次失败操作的错误状态. #include <winsock.h>

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()

WSAIsBlocking()

简述:

判断是否有阻塞调用正在进行. #include <winsock.h>

BOOL PASCAL FAR WSAIsBlocking ( void );

注释:

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

返回值:

TRUE 如果存在一个尚未完成的阻塞函数在等待完成.

FALSE 否则.

评价:

尽管在阻塞套接口上进行的调用对于应用程序来说似乎"阻塞"着,Windows Sockets DLL 必须放弃处理机以使其它应用程序可以使用.这意味着对于启动该阻塞调用的应用程序来说可能会重入-这依赖于它接收的消息.在这种情况

下,WSAIsBlocking()函数可用来确定在等待一个未完成的阻塞调用完成时,本任务是否重入.注意 Windows Sockets 禁止对每一线程多于一个未完成的调用.

关于 Windows Sockets 提供者的说明:

Windows Sockets 的实现必须禁止在每个线程上多于一次的未完成阻塞调用.

WSASetBlockingHook()

简述:

建立一个应用程序指定的阻塞钩子函数. #include <winsock.h>

FARPROC PASCAL FAR WSASetBlockingHook ( FARPROC lpBlockFunc ); lpBlockFunc 指向要安装的阻塞函数的函数指针.

注释:

本函数安装了一个新的函数,由 Windows Sockets 的实现用来实现阻塞套接口函数调用.

Windows Sockets 的实现中包含了一种缺省的机制,通过它可以实现阻塞套接口函数. 函数 WSASetBlockingHook()为应用程序提供了在"阻塞"时执行自己的程序,来代替缺省的函数.

当一个应用程序调用了一个阻塞的 Windows Sockets API 操作时,Windows Sockets 的实现启动该操作,然后进入了和下列伪代码相似的循环:

for(;;) {

/* flush messages for good user response */ while(BlockingHook())

;

/* check for WSACancelBlockingCall() */ if(operation_cancelled())

break;

/* check to see if operation completed */ if(operation_complete())

break; /* normal completion */

}

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

BOOL DefaultBlockingHook(void) {

MSG msg;

BOOL ret;

/* get the next message if any */

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

/* if we got one, process it */ if (ret) {

TranslateMessage(&msg); DispatchMessage(&msg);

}

/* TRUE if we got a message */ return ret;

}

WSASetBlockingHook()函数用来支持需要更复杂消息处理的应用程序-例如,使用了 MDI(多文本界面)的程序.它并不是为运行通常应用程序函数的.特别的,唯一可以由客户阻塞钩子函数调用的唯一 Windows Sockets API 函数是WSACancelBlockingCall()-它将引起阻塞循环中止.

本函数必须为 Windows 的非多线程版本和多线程版本(如Windows NT)提供每线程基础上的实现.这样, 它为特殊的任务或线程提供了不影响其它任务或线程的基础上替换阻塞机制的能力.

在Windows 的多线程版本中没有缺省的阻塞钩子函数-阻塞调用阻塞了进行该调用的线程.然而, 应用程序可以通过调用 WSASetBlockingHook()安装一个特定的阻塞钩子.这为依赖于阻塞钩子的应用程序提供了简单的可移植性.

返回值:

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

错误代码:

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

WSAENETDOWN Windows Sockets 的实现已经检测到网络子系统故障.

WSAEINPROGRESS 一个阻塞的 Windows Sockets 操作正在

进行.

参见:

WSAUnhookBlockingHook()

WSASetLastError()

简述:

设置可以被 WSAGetLastError()接收的错误代码. #include <winsock.h>

void PASCAL FAR WSASetLastError ( int iError );

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

代码.

注释:

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

关于 Windows Sockets 提供者的说明:

在 Win32 环境中,本函数将调用 SetLastError().

返回值:

无.

错误代码:

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

参见:

WSAGetLastError()

WSAStartup()

简述:

#include <winsock.h>

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()调用之后才能调用进一步的 Windows Sockets 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()函数并且要么去另一个 Windows Sockets DLL 中搜索,要么初始化失败.

本协议允许 Windows Sockets DLL 和 Windows Sockets 应用程序共同支持一定范围的Windows Sockets 版本.如果版本范围有重叠,应用程序就可以成功地使用 Windows Sockets DLL.下列的图表给出了 WSAStartup()在不同的应用程序和Windows Sockets DLL 版本中是如何工作的:

应用程序版本

wHighVersion

DLL 版本

最终结果

wVersionRequested

wVersion

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 ) {

/* Tell the user that we couldn't find a useable */

/* winsock.dll. */

return;

}

/* Confirm that the Windows Sockets DLL supports 1.1.*/

/* Note that if the DLL supports versions greater */

/* than 1.1 in addition to 1.1, it will still return */

/* 1.1 in wVersion since that is the version we */

/* requested. */

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

/* Tell the user that we couldn't find a useable */

/* winsock.dll. */

WSACleanup( ); return;

}

/* The Windows Sockets DLL is acceptable. Proceed. */

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

/* Make sure that the version requested is >= 1.1. */

/* The low byte is the major version and the high */

/* byte is the minor version. */

if ( LOBYTE( wVersionRequested ) < 1 ||

( LOBYTE( wVersionRequested ) == 1 && HIBYTE( wVersionRequested ) < 1 ) {

return WSAVERNOTSUPPORTED;

}

/* Since we only support 1.1, set both wVersion and */

/* wHighVersion to 1.1. */

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

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

一旦应用程序或 DLL 进行了一次成功的 WSAStartup()调用,它就可以继续进行其它所需的 Windows Sockets API 调用.当它完成了使用该 Windows Sockets DLL 的服务后,应用程序或 DLL 必须调用 WSACleanup()以允许 Windows Sockets 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 个套接口,因为可能有其它的 Windows Sockets 应用程序在使用.

iMaxUdpDg 以字节表示的可由 Windows Sockets 应用程序发送或接收的最大 UDP 数据报的大小.如果应用程序没有给出限制,iMaxUdpDg 为 0.在Berkeley 套接口的许多实现中,对于 UDP 数据报的导向有一个隐含的限制 8192 字节.Windows Sockets 的实现可以在分配碎片重组缓冲区的基础上给出界限.对于一般的 Windows Sockets 实现 iMaxUdpDg 的最小值为 512.注意不考虑iMaxUdpDg 的值,而试图在网络上发送一个大于最大传输单元(MTU)的广播数据报是不明智的.(Windows Sockets API 没有提供发现 MTU 的机制,但它必须不小于512 字节.)

lpVendorInfo 指向厂商规定数据结构的远指针.该结构的定义

(如果提供)超出了本规范的范围.

应用程序或 DLL 若需要多次得到 WSAData 结构信息,就必须多次调用WSAStartup().然而,wVersionRequired 参数假设在所有调用 WSAStartup()中都相同;也就是,应用程序或 DLL 不能在第一次调用 WSAStartup()后改变 Windows Sockets 的版本号.

对应于每一次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()

WSAUnhookBlockingHook()

简述:

恢复缺省的阻塞钩子函数.

#include <winsock.h>

int PASCAL FAR WSAUnhookBlockingHook ( void );

注释:

本函数除去了任何先前安装的阻塞钩子函数,并且重新安装缺省的阻塞钩子函数.

WSAUnhookBlockingHook()将肯定安装缺省的钩子函数,而非上一个.如果应用程序希望嵌套钩子函数-也就是,建立一个临时的钩子函数,然后返回前一个钩子函数(不论是缺省的还是由前面的 WSASetBlockingHook()建立的)-它必须储存和恢复 WSASetBlockingHook()的返回值;不能使用WSAUnhookBlockingHook().

在 Windows 的多线程版本(如 Windows NT)中没有缺省的阻塞钩子函数.调用WSAUnhookBlockingHook()去除了应用程序和任何阻塞调用(阻塞了进行该调用的线程本身)安装的所有阻塞钩子函数.

返回值:

0 操作成功.

SOCKET_ERROR 否则.同时可以调用 WSAGetLastError()获得

错误代码.

错误代码:

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

参见:

WSASetBlockingHook()