Windows Sockets 网络编程——第十章 支持例程
来源:互联网 发布:时间碎片软件 编辑:程序博客网 时间:2024/05/22 01:58
第十章 支持例程
10.1 启动与清除
每一个WinSock应用程序必须在开始操作前初始化WinSock的动态链接库(DLL),并在操作完成后通知DLL进行清除操作。WinSock应用程序在开始时必须调用WSAStartup()函数,结束时必须调用WSACleanup()函数。可以多次调用这两个函数,但是必须保证它们是成对出现的。
在系统内部,WSAStartup()函数从0开始增加引用计数量,而WSACleanup()函数减少引用计数量。当引用计数量减为0时,WinSock DLL才释放资源。
10.1.1 WSAStartup()
WSAStartup()函数必须是WinSock应用程序使用的第一个WinSock函数。否则,其他的WinSock API函数都将会失败并返回错误值WSAENOTNITIALISED。WinSock DLL使用这个函数来注册调用任务并分配必要的资源。
下面是WSAStartup()函数的原型:
int WSAAPI WSAStartup( WORD wVersionRequired, //hightest version of WinSock API LPWSADATA lpWSAData //ptr to struct to receive details on Windows Sockets implementation);
wVersionRequired:应用程序要求的主要和次要的版本号。LSB是主要的版本号,MSB是次要的版本号。
lpWSAData:指向WinSock应用程序提供的缓存区,缓存区中填入的内容为有关WinSock实现的特有信息。
这个函数与其它很多函数有所不同,它在成功时返回0值,返回错误值表示失败。函数的每次成功调用,都将会使引用计数增加1.
typedef struct WSAData { WORD wVersion; //version app expected to use WORD wHighVersion; //hightest version available#ifdef _WIN64 unsigned short iMaxSockets; //max sockets available unsigned short iMaxUdpDg; // max datagram size char FAR * lpVendorInfo; //no format char szDescription[WSADESCRIPTION_LEN+1];//no format char szSystemStatus[WSASYS_STATUS_LEN+1];//no format#else char szDescription[WSADESCRIPTION_LEN+1];//no format char szSystemStatus[WSASYS_STATUS_LEN+1];//no format unsigned short iMaxSockets; //max sockets available unsigned short iMaxUdpDg; // max datagram size char FAR * lpVendorInfo; //no format#endif} WSADATA, FAR * LPWSADATA;
应用程序所请求的版本号不能低于WinSock DLL所支持的最低版本号,但可以高于WinSock DLL所支持的最高版本号。例如,WinSock DLL最高支持2.2的版本,我们可以请求2.2以上的版本3.0。最低支持1.1版本,这时我们请求1.0版本的将会请求失败。
10.1.2 WSACleanup()
每一个WSAStartup()函数的成功调用,都要有一个与之相匹配的WSACleanup()函数调用。WSACleanup()函数的成功调用都将使引用计数减1.
int WSAAPI WSACleanup( void );// 0 on success, or SOCKET_ERROR
WSACleanup()函数调用总是立即返回。若执行成功,WSACleanup()会返回0值。若执行失败,WSACleanup()会返回SOCKET_ERROR。
10.2 字节顺序
主机字节顺序采用的是小尾端在前。网络字节顺序采用的是大尾端在前。通常情况下,WinSock函数的任何多字节输入参数和WinSock结构的多字节域值都应该采用网络字节顺序。协议号、getprotobynumber()函数或WSAAsyncGetProtoByNumber()函数的输入参数例外。
字节顺序函数
- htons()函数将16位短整型数据从主机顺序转为网络顺序,ntohs()函数将16位短整型数据从网络顺序转为主机顺序。
- htonl()函数将32位长整型数据从主机顺序转为网络顺序,htohl()函数将32位短整型数据从网络顺序转为主机顺序.
u_short WSAAPI htons( u_short hostshort );u_short WSAAPI ntohs( u_short netshort );u_long WSAAPI ntohl( u_long netlong );u_long WSAAPI htonl( u_long hostlong );
这些函数调用不会失败,它们返回与输入参数值大小相同的值,但是它们并不总是执行重排序操作。如果当前系统的原生字节顺序是大尾端,那么上面的这些函数将不会执行任何操作。
10.3 服务名称与端口号
每一个服务都有一个端口号,有很多服务还有名称。WinSock API有4个服务解析函数:getservbyname()、WSAAsyncGetServByName()、getservbyport()和WSAAsyncGetServByPort()。
10.3.1 servent 结构
所有的服务解析函数都会在servent结构中返回它们的结果。
struct servent { char FAR * s_name; /* official service name */ char FAR * FAR * s_aliases; /* alias list */#ifdef _WIN64 char FAR * s_proto; /* protocol to use */ short s_port; /* port # */#else short s_port; /* port # */ char FAR * s_proto; /* protocol to use */#endif};typedef struct servent SERVENT;typedef struct servent *PSERVENT;typedef struct servent FAR *LPSERVENT;
s_name:服务的公开名称。通常服务的名称有小写字母构成。
s_aliases:以NULL结束的别名字符串数组(即可替换的服务名称),它以空指针结束。
s_port:访问服务的端口号。
s_proto:以空字符结束的协议名称字符串,与用户要求的名称效用。
10.3.2 服务解析
getservbyname(),阻塞至服务名称解析操作完成。这个函数通常反问本地的磁盘文件进行解析,所以返回结果的速度很快。
WSAAsyncGetServByName(),立即返回,在服务名称解析操作完成后异步地通知应用程序。
- getservbyname()
struct servent FAR * WSAAPI getservbyname( const char FAR * name, //pointer to service name const char FAR * proto //pointer to protocol name or NULL to return first match of service name);
getservbyname()函数返回一个指向servent结构的指针。调用getservbyname()函数后,在其他的WinSock函数调用改变servent结构内容前,需要将servent的内容读取进行保存。一定不能试图释放或者改变结构的内容,否则会出现保护故障。
2.WSAAsyncGetServByName()
HANDLE WSAAPI WSAAsyncGetServByName( HWND hWnd, // handle of window to rcv msg on completion u_int wMsg, // message to be rcvd on completion const char FAR * name, // ptr to service name to be resolved const char FAR * proto,// ptr to protocol name (may be NULL) char FAR * buf, // ptr to data area to rcv servent data int buflen // size of data area buf above);
WSAAsyncGetServByName() 函数如果操作成功,将返回一个非0异步查询句柄,当操作完成后,可以使用这个句柄来标识应答结果。
10.3.3 端口解析
- getservbyport()
struct servent FAR * WSAAPI getservbyport( int port, // port number, in network byte order const char FAR * proto // pointer to protocol name or NULL to return first match of service port);
此函数一直阻塞至端口号解析操作完成。其返回值是一个指向系统缓存区的指针。操作失败,返回值为空指针。
2. WSAAsyncGetServByPort()
HANDLE WSAAPI WSAAsyncGetServByPort( HWND hWnd, // handle to window to rcv msg on completion u_int wMsg, // message to be rcvd on completion int port, // port number to be resolved (net byte order) const char FAR * proto,// ptr to protocol name (may be NULL) char FAR * buf, // ptr to data area to rcv servent data int buflen // size of data area buf above);
WSAAsyncGetServByPort()函数与WSAAsyncGetServByName()函数相比,除了使用端口号替换服务名称和别名,其他内容都相同。这两个函数在同种情况下返回结果相同。
10.4 协议名称与协议号
每一个协议都有一个协议号。这些号码在Winsock[2].h中定义。协议解析与服务和主机解析类似,但很少使用协议解析,因为协议值不能变化。
10.4.1 protoent结构
所有的协议解析函数都将返回值放入protoent结构中。
struct protoent { char FAR * p_name; /* official protocol name */ char FAR * FAR * p_aliases; /* alias list */ short p_proto; /* protocol number */};typedef struct protoent PROTOENT;typedef struct protoent *PPROTOENT;typedef struct protoent FAR *LPPROTOENT;
p_name:协议的正式名称,通常有小写字母构成。
p_aliases:一空字符结束的别名字符串数组,它以空指针结束。通常,用大写字符的协议名称是别名。
p_proto:以主机字节顺序描述的协议号。
10.4.2 协议名称解析
协议名称解析函数getprotobyname()和WSAAsyncGetProtoByName(),前者是阻塞模式,后者以异步方式进行。由于协议值不会像端口号那样发生改变,所以,这两个函数实际上是很少被使用到的。
1. getprotobyname()
struct protoent FAR * WSAAPI getprotobyname( const char FAR * name // pointer to protocol name);
name:以空字符结束的字符串,它包含有需要解析的协议名称和别名。
getprotobyname()函数操作失败返回0值(空指针)。可以通过WSAGetLastError()函数得到错误值,从而找到失败的原因。如果操作成功,函数将返回一个指针,指向系统缓存中protoent结构。在获得返回值后,应该立即引用protoent结构中的内容。
2. WSAAsyncGetProtoByName()
HANDLE WSAAPI WSAAsyncGetProtoByName( HWND hWnd, // handle to window to rcv msg on completion u_int wMsg, // message to be rcvd on completion const char FAR * name,// ptr to protocol name to be resolved char FAR * buf, // ptr to data area to rcv protoent data int buflen // size of data area buf above);
WSAAsyncGetProtoByName()总是在协议名称解析操作完成前立即返回。如果操作成功,WSAAsyncGetProtoByName()函数将返回一个非0异步查询句柄。
10.4.3 协议号解析
getprotobynumber()与WSAAsyncGetProtoByNumber()函数都用协议号作为输入参数,并将正确的值填入协议的结构中。
struct protoent FAR * WSAAPI getprotobynumber( int number // protocol number, in host byte order);HANDLE WSAAPI WSAAsyncGetProtoByNumber( HWND hWnd, // handle to window to rcv msg on completion u_int wMsg, // message to be rcvd on completion const char FAR * name,// ptr to protocol name to be resolved char FAR * buf, // ptr to data area to rcv protoent data int buflen // size of data area buf above);
number:协议号值与IP报头中协议字段的标准值一致。
- Windows Sockets 网络编程——第十章 支持例程
- Windows sockets 网络编程(1) — 综述
- Windows sockets 网络编程(1) — 综述 .
- Windows Sockets 网络编程
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- 转:Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设
- Windows sockets 网络编程(二) — 阻塞模式开发
- Windows sockets 网络编程(三)— 非阻塞模式开发
- Windows sockets 网络编程(2) — 阻塞模式开发
- Windows sockets 网络编程(3) — 非阻塞模式开发
- Windows Sockets 网络编程——第四章 网络应用程序工作机制
- Windows Sockets 网络编程——第三章 TCP/IP协议服务
- Windows Sockets 网络编程(三)
- 正则表达式语法
- java使用ffmpeg和mencoder做视频格式转换
- perl 切换cpan
- 第五课 生成学习算法
- [leetcode] 155.Min Stack
- Windows Sockets 网络编程——第十章 支持例程
- [转]URL传值带加号“+”的问题的解决方法
- 数据挖掘之关联分析六(子图模式)
- 我爸爸是个程序员
- error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
- buildPyramid函数
- OC基础 -- 集合 和 常见对象
- DDX_Control和DDX_Text的区别
- 关于数据库事务、隔离级别、锁的理解与整理