论坛: 编程破解 标题: Windows Sockets 规范及应用(第五章 套接口库函数参考2) 复制本贴地址    
作者: xiaoxingchi [xiaoxingchi]    论坛用户   登录
5.2.6 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()

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

5.3 Windows扩展函数

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

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

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

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

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

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

5.3.7 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调用.例如,下列的事件序列是可能的:
(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消息,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()

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


5.3.9 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 指出指定的参数之一是非法的.

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

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

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

#include <winsock.h>

BOOL PASCAL FAR WSAIsBlocking ( void );

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

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

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

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

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

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

#include <winsock.h>

void PASCAL FAR WSASetLastError ( int iError );

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

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

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

返回值: 
无.

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

参见:
WSAGetLastError()

5.3.15 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版本中是如何工作的:

应用程序版本 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 ) {
/* 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()

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



地主 发表时间: 04/29 08:44

论坛: 编程破解

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号