📄 22.htm
字号:
<P>	某一个应用程序也可能喜欢线内处理紧急数据,即把其作为普通数据流的一部分。这可以靠设置套接口选项中的</FONT>SO_OOBINLINE<FONT FACE="宋体" LANG="ZH-CN">来实现(参见</FONT>5.1.21<FONT FACE="宋体" LANG="ZH-CN">节,</FONT>setsockopt()<FONT FACE="宋体" LANG="ZH-CN">)。在这种情况下,应用程序可能希望确定未读数据中的哪一些是“紧急”的(“紧急”这一术语通常应用于线内带外数据)。为了达到这个目的,在</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">的实现中就要在数据流保留一个逻辑记号来指出带外数据从哪一点开始发送,一个应用程序可以使用</FONT>SIOCATMARK ioctlsocket()<FONT FACE="宋体" LANG="ZH-CN">命令(参见</FONT>5.1.12<FONT FACE="宋体" LANG="ZH-CN">节)来确定在记号之前是否还有未读入的数据。应用程序可以使用这一记号与其对方进行重新同步。</P>
<P>	</FONT>WSAAsyncSelect()<FONT FACE="宋体" LANG="ZH-CN">函数可以用于处理对带外数据到来的通知。</P>
<P> </P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626796"><A NAME="_Toc336792862"><A NAME="_Toc336793338"></FONT><FONT SIZE=5>2.2.4 </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>广播</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	数据报套接口可以用来向许多系统支持的网络发送广播数据包。要实现这种功能,网络本身必须支持广播功能,因为系统软件并不提供对广播功能的任何模拟。广播信息将会给网络造成极重的负担,因为它们要求网络上的每台主机都为它们服务,所以发送广播数据包的能力被限制于那些用显式标记了允许广播的套接口中。广播通常是为了如下两个原因而使用的:</FONT>1. <FONT FACE="宋体" LANG="ZH-CN">一个应用程序希望在本地网络中找到一个资源,而应用程序对该资源的地址又没有任何先验的知识。</FONT>2. <FONT FACE="宋体" LANG="ZH-CN">一些重要的功能,例如路由要求把它们的信息发送给所有可以找到的邻机。</P>
<P>	被广播信息的目的地址取决于这一信息将在何种网络上广播。</FONT>Internet<FONT FACE="宋体" LANG="ZH-CN">域中支持一个速记地址用于广播-</FONT>INADDR_BROADCAST<FONT FACE="宋体" LANG="ZH-CN">。由于使用广播以前必须捆绑一个数据报套接口,所以所有收到的广播消息都带有发送者的地址和端口。</P>
<P>	某些类型的网络支持多种广播的概念。例如</FONT>IEEE802.5<FONT FACE="宋体" LANG="ZH-CN">令牌环结构便支持链接层广播指示,它用来控制广播数据是否通过桥接器发送。</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">规范没有提供任何机制用来判断某个应用程序是基于何种网络之上的,而且也没有任何办法来控制广播的语义。</P>
<P> </P>
</FONT><B><FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626797"><A NAME="_Toc336792863"><A NAME="_Toc336793339"></FONT><FONT FACE="Arial" SIZE=5>2.3 </FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>字节顺序</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</FONT>Intel<FONT FACE="宋体" LANG="ZH-CN">处理器的字节顺序是和</FONT>DEC VAX<FONT FACE="宋体" LANG="ZH-CN">处理器的字节顺序一致的。因此它与</FONT>68000<FONT FACE="宋体" LANG="ZH-CN">型处理器以及</FONT>Internet<FONT FACE="宋体" LANG="ZH-CN">的顺序是不同的,所以用户在使用时要特别小心以保证正确的顺序。</P>
<P>	任何从</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">函数对</FONT>IP<FONT FACE="宋体" LANG="ZH-CN">地址和端口号的引用和传送给</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">函数的</FONT>IP<FONT FACE="宋体" LANG="ZH-CN">地址和端口号均是按照网络顺序组织的,这也包括了</FONT>sockaddr_in<FONT FACE="宋体" LANG="ZH-CN">结构这一数据类型中的</FONT>IP<FONT FACE="宋体" LANG="ZH-CN">地址域和端口域(但不包括</FONT>sin_family<FONT FACE="宋体" LANG="ZH-CN">域)。</P>
<P>	考虑到一个应用程序通常用与“时间”服务对应的端口来和服务器连接,而服务器提供某种机制来通知用户使用另一端口。因此</FONT>getservbyname()<FONT FACE="宋体" LANG="ZH-CN">函数返回的端口号已经是网络顺序了,可以直接用来组成一个地址,而不需要进行转换。然而如果用户输入一个数,而且指定使用这一端口号,应用程序则必须在使用它建立地址以前,把它从主机顺序转换成网络顺序(使用</FONT>htons()<FONT FACE="宋体" LANG="ZH-CN">函数)。相应地,如果应用程序希望显示包含于某一地址中的端口号(例如从</FONT>getpeername()<FONT FACE="宋体" LANG="ZH-CN">函数中返回的),这一端口号就必须在被显示前从网络顺序转换到主机顺序(使用</FONT>ntohs()<FONT FACE="宋体" LANG="ZH-CN">函数)。</P>
<P>	由于</FONT>Intel<FONT FACE="宋体" LANG="ZH-CN">处理器和</FONT>Internet<FONT FACE="宋体" LANG="ZH-CN">的字节顺序是不同的,上述的转换是无法避免的,应用程序的编写者应该使用作为</FONT>Windows Sockets API<FONT FACE="宋体" LANG="ZH-CN">一部分的标准的转换函数,而不要使用自己的转换函数代码。因为将来的</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">实现有可能在主机字节顺序与网络字节顺序相同的机器上运行。因此只有使用标准的转换函数的应用程序是可移植的。</P>
<P> </P>
</FONT><B><FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626798"><A NAME="_Toc336792864"><A NAME="_Toc336793340"></FONT><FONT FACE="Arial" SIZE=5>2.4 </FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>套接口属性选项</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">规范支持的套接口属性选项都列在对</FONT>setsockopt()<FONT FACE="宋体" LANG="ZH-CN">函数和</FONT>getsockopt()<FONT FACE="宋体" LANG="ZH-CN">函数的叙述中。任何一个</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">实现必须能够识别所有这些属性选项,并且对每一个属性选项都返回合理的数值。每一个属性选项的缺省值列在下表中:</P>
<P>	选项</FONT> <FONT FACE="宋体" LANG="ZH-CN">类型</FONT> <FONT FACE="宋体" LANG="ZH-CN">含义</FONT> <FONT FACE="宋体" LANG="ZH-CN">缺省值</FONT> <FONT FACE="宋体" LANG="ZH-CN">注意事项</P>
<P>	</FONT>SO_ACCEPTCON BOOL <FONT FACE="宋体" LANG="ZH-CN">套接口正在监听。</FONT> FALSE</P>
<P>	SO_BROADCAST BOOL <FONT FACE="宋体" LANG="ZH-CN">套接口被设置为可以</FONT> FALSE</P>
<P>						 <FONT FACE="宋体" LANG="ZH-CN">发送广播数据。</P>
<P>	</FONT>SO_DEBUG BOOL <FONT FACE="宋体" LANG="ZH-CN">允许</FONT>Debug<FONT FACE="宋体" LANG="ZH-CN">。</FONT> FALSE (*)</P>
<P>	S0_DONTLINGER BOOL <FONT FACE="宋体" LANG="ZH-CN">如果为真,</FONT>SO_LINGER TRUE</P>
<P>						 <FONT FACE="宋体" LANG="ZH-CN">选项被禁止。</P>
<P>	</FONT>SO_DONTROUTE BOOL <FONT FACE="宋体" LANG="ZH-CN">路由被禁止。</FONT> FALSE (*)</P>
<P>	SO_ERROR int <FONT FACE="宋体" LANG="ZH-CN">得到并且清除错误状态。</FONT> 0</P>
<P>	SO_KEEPALIVE BOOL <FONT FACE="宋体" LANG="ZH-CN">活跃信息正在被发送。</FONT> FALSE</P>
<P>	SO_LINGER struct <FONT FACE="宋体" LANG="ZH-CN">返回目前的</FONT>linger<FONT FACE="宋体" LANG="ZH-CN">信息。</FONT> l_onoff </P>
<P>				 linger <FONT FACE="宋体" LANG="ZH-CN">为</FONT>0</P>
<P>				 FAR *</P>
<P>	SO_OOBINLINE BOOL <FONT FACE="宋体" LANG="ZH-CN">带外数据正在普通数据流</FONT> FALSE</P>
<P>						 <FONT FACE="宋体" LANG="ZH-CN">中被接收。</P>
<P>	</FONT>SO_RCVBUF int <FONT FACE="宋体" LANG="ZH-CN">接收缓冲区大小。</FONT> <FONT FACE="宋体" LANG="ZH-CN">决定于实现</FONT> (*)</P>
<P>	SO_REUSEADDR BOOL <FONT FACE="宋体" LANG="ZH-CN">该套接口捆绑的地址</FONT> FALSE</P>
<P>						 <FONT FACE="宋体" LANG="ZH-CN">是否可被其他人使用。</P>
<P>	</FONT>SO_SNDBUF int <FONT FACE="宋体" LANG="ZH-CN">发送缓冲区大小。</FONT> <FONT FACE="宋体" LANG="ZH-CN">决定于实现</FONT> (*)</P>
<FONT FACE="宋体" LANG="ZH-CN">
<P>	</FONT>SO_TYPE int <FONT FACE="宋体" LANG="ZH-CN">套接口类型(如</FONT> <FONT FACE="宋体" LANG="ZH-CN">和套接口被</P>
<P>						</FONT> SOCK_STREAM<FONT FACE="宋体" LANG="ZH-CN">)。</FONT> <FONT FACE="宋体" LANG="ZH-CN">创建时一致</P>
<P>	</FONT>TCP_NODELAY BOOL <FONT FACE="宋体" LANG="ZH-CN">禁止采用</FONT>Nagle <FONT FACE="宋体" LANG="ZH-CN">决定于实现</P>
</FONT><P> <FONT FACE="宋体" LANG="ZH-CN">进行合并传送。</P>
<P>	</FONT>(*) Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">实现有可能在用户调用</FONT>setsockopt()<FONT FACE="宋体" LANG="ZH-CN">函数时忽略这些属性,并且在用户调用</FONT>getsockopt()<FONT FACE="宋体" LANG="ZH-CN">函数时返回一个没有变化的值。或者它可能在</FONT>setsockopt()<FONT FACE="宋体" LANG="ZH-CN">时接受某个值,并且在</FONT>getsockopt()<FONT FACE="宋体" LANG="ZH-CN">时返回相应的数值,但事实上并没有在任何地方使用它。</P>
<P> </P>
</FONT><B><FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626799"><A NAME="_Toc336792865"><A NAME="_Toc336793341"></FONT><FONT FACE="Arial" SIZE=5>2.5 </FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>数据库文件</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</FONT>getXbyY()<FONT FACE="宋体" LANG="ZH-CN">和</FONT>WSAAyncGetXByY()<FONT FACE="宋体" LANG="ZH-CN">这一类的例程是用来得到某种特殊的网络信息的。</FONT>getXbyY()<FONT FACE="宋体" LANG="ZH-CN">例程最初(在第一版的</FONT>BERKELY UNIX<FONT FACE="宋体" LANG="ZH-CN">中)是被设计成一种在文本数据库中查询信息的机制。虽然</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">实现可能用不同的方式来得到这些信息,但</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">应用程序要求通过</FONT>getXbyY()<FONT FACE="宋体" LANG="ZH-CN">或</FONT>WSAAyncGetXByY()<FONT FACE="宋体" LANG="ZH-CN">这一类例程得到的信息是一致。</P>
<P> </P>
</FONT><B><FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626800"><A NAME="_Toc336792866"><A NAME="_Toc336793342"></FONT><FONT FACE="Arial" SIZE=5>2.6 </FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>与</FONT><FONT FACE="Arial" SIZE=5>Berkeley</FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>套接口的不同</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	有一些很有限的地方,</FONT>Windows Sockets API<FONT FACE="宋体" LANG="ZH-CN">必须与从严格地坚持</FONT>Berkeley<FONT FACE="宋体" LANG="ZH-CN">传统风格中解放出来。通常这么做是因为在</FONT>Windows<FONT FACE="宋体" LANG="ZH-CN">环境中实现的难度。</P>
<P> </P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626801"><A NAME="_Toc336792867"><A NAME="_Toc336793343"></FONT><FONT SIZE=5>2.6.1 </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>套接口数据类型和错误数值</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">规范中定义了一个新的数据类型</FONT>SOCKET<FONT FACE="宋体" LANG="ZH-CN">,这一类型的定义对于将来</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">规范的升级是必要的。例如在</FONT>Windows NT<FONT FACE="宋体" LANG="ZH-CN">中把套接口作为文件句柄来使用。这一类型的定义也保证了应用程序向</FONT>Win/32<FONT FACE="宋体" LANG="ZH-CN">环境的可移植性。因为这一类型会自动地从</FONT>16<FONT FACE="宋体" LANG="ZH-CN">位升级到</FONT>32<FONT FACE="宋体" LANG="ZH-CN">位。</P>
<P>	在</FONT>UNIX<FONT FACE="宋体" LANG="ZH-CN">中所有句柄包括套接口句柄,都是非负的短整数,而且一些应用程序把这一假设视为真理。</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">句柄则没有这一限制,除了</FONT>INVALID_SOCKET<FONT FACE="宋体" LANG="ZH-CN">不是一个有效的套接口外,套接口可以取从</FONT>0<FONT FACE="宋体" LANG="ZH-CN">到</FONT>INVALID_SOCKET-1<FONT FACE="宋体" LANG="ZH-CN">之间的任意值。</P>
<P>因为</FONT>SOCKET<FONT FACE="宋体" LANG="ZH-CN">类型是</FONT>unsigned<FONT FACE="宋体" LANG="ZH-CN">,所以编译已经存在于</FONT>UNIX<FONT FACE="宋体" LANG="ZH-CN">环境中的应用程序的源代码可能会导致</FONT>signed/unsigned<FONT FACE="宋体" LANG="ZH-CN">数据类型不匹配的警告。</P>
<P>	这还意味着,在</FONT>socket()<FONT FACE="宋体" LANG="ZH-CN">例程和</FONT>accept()<FONT FACE="宋体" LANG="ZH-CN">例程返回时,检查是否有错误发生就不应该再使用把返回值和</FONT>-1<FONT FACE="宋体" LANG="ZH-CN">比较的方法,或判断返回值是否为负(这两种方法在</FONT>BSD<FONT FACE="宋体" LANG="ZH-CN">中都是很普通,很合法的途径)。取而代之的是,一个应用程序应该使用常量</FONT>INVALID_SOCKET<FONT FACE="宋体" LANG="ZH-CN">,该常量已在</FONT>WINSOCK.H<FONT FACE="宋体" LANG="ZH-CN">中定义。</P>
<P>	例如:</P>
<P>		</FONT> <FONT FACE="宋体" LANG="ZH-CN">典型的</FONT>BSD<FONT FACE="宋体" LANG="ZH-CN">风格:</P>
<P>		</FONT> s = socket(...);</P>
<P>		 if (s == -1) /* of s<0 */</P>
<P>			 {...}</P>
<P>		 <FONT FACE="宋体" LANG="ZH-CN">更优良的风格:</P>
<P>		</FONT> s = socket(...);</P>
<P>		 if (s == INVALID_SOCKET)</P>
<P>			 {...}</P>
<P> </P>
<B><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626802"><A NAME="_Toc336792868"><A NAME="_Toc336793344"></FONT><FONT SIZE=5>2.6.2 select()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>函数和</FONT><FONT SIZE=5>FD_*</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>宏</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	由于一个套接口不再表示了</FONT>UNIX<FONT FACE="宋体" LANG="ZH-CN">风格的小的非负的整数,</FONT>select()<FONT FACE="宋体" LANG="ZH-CN">函数在</FONT>Windows Sockets API<FONT FACE="宋体" LANG="ZH-CN">中的实现有一些变化:每一组套接口仍然用</FONT>fd_set<FONT FACE="宋体" LANG="ZH-CN">类型来代表,但是它并不是一个位掩码。整个组的套接口是用了一个套接口的数组来实现的。为了避免潜在的危险,应用程序应该坚持用</FONT>FD_XXX<FONT FACE="宋体" LANG="ZH-CN">宏来设置,初始化,清除和检查</FONT>fd_set<FONT FACE="宋体" LANG="ZH-CN">结构。</P>
<P> </P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626803"><A NAME="_Toc336792869"><A NAME="_Toc336793345"></FONT><FONT SIZE=5>2.6.3 </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>错误代码-</FONT><FONT SIZE=5>errno,h_errno,WSAGetLastError()</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</FONT>Windows Sockets<FONT FACE="宋体" LANG="ZH-CN">实现所设置的错误代码是无法通过
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -