⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 4-1.html

📁 WinSock编程规范及应用
💻 HTML
字号:
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb_2312-80">
<META NAME="Generator" CONTENT="Microsoft Word 97">
<TITLE>第四章 Windows Socket 1</TITLE>
</HEAD>
<BODY>

<B><FONT FACE="宋体" LANG="ZH-CN" SIZE=6><P><A NAME="_Toc336626817"><A NAME="_Toc336792900"><A NAME="_Toc336793376">第四章</FONT><FONT SIZE=6> Windows Socket 1.1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=6>库函数概览</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626818"><A NAME="_Toc336792901"><A NAME="_Toc336793377"></FONT><FONT FACE="Arial" SIZE=5>4.1 </FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>套接口函数</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>规范包含了以下</FONT><FONT SIZE=3>Berkeley</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>风格的套接口例程:</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>accept()*       </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>响应联结请求,并且新建一个套接口。原来的套接口则返回监听状态。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>bind()          </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把一个本地的名字和一个无名的套接口捆绑起来。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>closesocket()*  </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把套接口从拥有对象参考表中取消。该函数只有在</FONT><FONT SIZE=3>SO_LINGER</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>被设置时才会阻塞。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>connect()*      </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>初始化到一个指定套接口上的连接。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>getpeername()   </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>得到连接在指定套接口上的对等通讯方的名字。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>getsockname()   </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>得到指定套接口上当前的名字。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>getsockopt()    </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>得到与指定套接口相关的属性选项。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>htonl()         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把</FONT><FONT SIZE=3>32</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>位的数字从主机字节顺序转换到网络字节顺序。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>htons()         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把</FONT><FONT SIZE=3>16</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>位的数字从主机字节顺序转换到网络字节顺序。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>inet_addr()     </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把一个</FONT><FONT SIZE=3>Internet</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>标准的</FONT><FONT SIZE=3>"."</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>记号地址转换成</FONT><FONT SIZE=3>Internet</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>地址数值。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>inet_ntoa()     </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把</FONT><FONT SIZE=3>Internet</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>地址数值转换成带</FONT><FONT SIZE=3>"."</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的</FONT><FONT SIZE=3>ASCII</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>字符串。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>ioctlsocket()   </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>为套接口提供控制。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>listen()        </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>监听某一指定套接口上连接请求的到来。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>ntohl()         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把</FONT><FONT SIZE=3>32</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>位数字从网络字节顺序转换为主机字节顺序。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>ntons()         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>把</FONT><FONT SIZE=3>16</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>位数字从网络字节顺序转换为主机字节顺序。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>recv()*         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>从一个已连接的套接口接收数据。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>recvfrom()*     </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>从一个已连接的或未连接的套接口接收数据。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>select()*       </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>执行同步</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>多路复用。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>send()*         </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>从一已连接的套接口发送数据。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>sendto()*       </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>从已连接或未连接的套接口发送数据。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>setsockopt()    </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>设置与指定套接口相关的属性选项。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>shutdown()      </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>关闭一部分全双工的连接。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>socket()        </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>创建一个通讯端点并返回一个套接口。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">&#9;</FONT><FONT SIZE=3>*</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>表示例程在应用于阻塞套接口时会阻塞。</P>
<P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626819"><A NAME="_Toc336792902"><A NAME="_Toc336793378"></FONT><FONT SIZE=5>4.1.1 </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>阻塞</FONT><FONT SIZE=5>/</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5>非阻塞和数据易失性</A></A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">&#9;阻塞是在把应用程序从</FONT><FONT SIZE=3>Berkeley</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>套接口环境中移植到</FONT><FONT SIZE=3>Windows</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>环境中的一个主要焦点。阻塞是指唤起一个函数,该函数直到相关操作完成时才返回。由于操作可能需要任意长的时间才能完成,于是问题就出现了。最明显的一个例子就是</FONT><FONT SIZE=3>recv()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,这个函数会一直处于阻塞状态直到收到对方系统发送的数据。在</FONT><FONT SIZE=3>Berkeley</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>套接口模型中,一个套接口的操作的缺省行为是阻塞方式的,除非程序员显式地请求该操作为非阻塞方式。我们强烈推荐程序员在尽可能的情况下使用非阻塞方式(异步方式)的操作。因为非阻塞方式的操作能够更好地在非占先的</FONT><FONT SIZE=3>Windows</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>环境下工作。程序员应该在绝对必要的时候才采用阻塞方式。而且在你必须使用阻塞方式的操作前仔细阅读并理解这一部分。</P>
<P ALIGN="JUSTIFY">&#9;即使在阻塞方式下,有些操作(例如</FONT><FONT SIZE=3>bind(),getsockopt(),getpeername()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>)也会立刻完成。对于这些操作,阻塞方式和非阻塞方式并没有什么两样。其他一些操作(例如</FONT><FONT SIZE=3>recv()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>)可能立刻完成,也可能需要阻塞一段随机的时间才能完成。这都取决于不同的传输情况。当用于阻塞套接口时,这些操作被认为是工作于阻塞方式的,所有会阻塞的例程在以前或以后的列表中都打上了星号作标记。</P>
<P ALIGN="JUSTIFY">&#9;在</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>实现中,一个无法立刻完成的阻塞操作是按如下方式处理的。</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>先初始化操作,然后进入一个循环,在循环中发送收到的任何信息-为了使在必要时把处理器交给其他线程,然后检查</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>功能是否完成。如果功能完成了,或者</FONT><FONT SIZE=3>WSACancelBlockingCall()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>被唤起,阻塞操作以一个适当的返回值结束。完整的关于这种机制的描述,请参见</FONT><FONT SIZE=3>5.3.13</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>节,</FONT><FONT SIZE=3>WSASetBlockingHook()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,这一部分还包括了对于各种函数伪代码的讨论。</P>
<P ALIGN="JUSTIFY">&#9;如果一个正在运行某一阻塞操作的进程收到了一个</FONT><FONT SIZE=3>Windows</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>消息,那么应用程序有可能试图发出另一个</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>调用,由于很难安全地处理这种情形,</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>规范不支持这种应用程序的工作方式。在这种情况下,有两个函数可以帮助程序员。</FONT><FONT SIZE=3>WSAIsBlocking()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>可以用来确定在该进程上是否有阻塞的</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>调用。</FONT><FONT SIZE=3>WSACancelBlookingCall()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>可以用来取消在线的阻塞调用,如果有的话。任何其他的</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>函数如果在这种情况下被调用,则会失败并返回错误代码</FONT><FONT SIZE=3>WSAEINPROGRESS</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。要强调的是,这一限制适用于所有阻塞和非阻塞的操作。</P>
<P ALIGN="JUSTIFY">&#9;虽然这种机制对于简单的应用程序已经足够了,但这不能支持高级应用程序的复杂的消息发送要求。(例如,那些</FONT><FONT SIZE=3>MDI</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>模型的用户)对于这样的应用程序,</FONT><FONT SIZE=3>Windows Sockets API</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>设计了</FONT><FONT SIZE=3>WSASetBlockingHook()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>函数,这个函数可以允许程序员定义特殊的阻塞钩子来代替上面讨论的缺省消息发送例程。</P>
<P ALIGN="JUSTIFY">&#9;只有在以下都为真时,</FONT><FONT SIZE=3>Windows Sockets DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>才调用阻塞钩子函数:例程是被定义为可以阻塞的,指定的套接口也是阻塞套接口,而且请求不能被立刻完成。(套接口是被缺省地设为阻塞方式的,但</FONT><FONT SIZE=3>IOCTL FIONBIO</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>和</FONT><FONT SIZE=3>WSAAsyncSelect()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>都可以把套接口设置成为非阻塞模式)。如果应用程序只使用非阻塞方式的套接口,而且使用</FONT><FONT SIZE=3>WSAAsyncSelect()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>和</FONT><FONT SIZE=3>/</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>或</FONT><FONT SIZE=3>WSAAsyncGetXByY()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>例程,而不是使用</FONT><FONT SIZE=3>select()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>和</FONT><FONT SIZE=3>/</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>或</FONT><FONT SIZE=3>getXbyY()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>例程,那么阻塞钩子函数就永远也不会被调用,应用程序也不用再操心由于阻塞钩子函数而带来的重入问题。</P>
<P ALIGN="JUSTIFY">&#9;如果一个应用程序在唤起异步或非阻塞方式调用时使用了一个内存对象的指针(例如一个缓冲区,或者一个全程变量)作为参数,那么应用程序要保证那个对象在</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>实现的整个操作中都可得到并使用。应用程序不能再唤起可能影响到内存唤射或寻址能力的其他的</FONT><FONT SIZE=3>Windows</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>函数。在多线程系统中,应用程序也有责任使用某种同步机制来协调对内存对象的存取。</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>实现不能,也不会提出这种事情。没有遵守这条规则,所可能产生的后果已不在规范讨论的范围之内。</P>
<P ALIGN="JUSTIFY"></P></FONT></BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -