NSPR 池方法¶
本技术说明文档记录了 PRFileDesc 的轮询方法。轮询方法不要与 PR_Poll 函数混淆。轮询方法作用于单个 Netscape Portable Runtime (NSPR) 文件描述符,而 PR_Poll 作用于一组 NSPR 文件描述符。PR_Poll 在后台使用轮询方法,但也可以直接使用轮询方法。
我们认为在网络传输层之上有一堆 NSPR I/O 层。每个 I/O 层由一个 PRFileDesc 结构表示,该层的协议由一个 PRIOMethods 表实现。底层是底层网络传输的包装器。NSPR 库使用套接字 API 提供了底层的参考实现,但是您可以使用其他网络传输 API 提供您自己的底层实现。轮询方法是 PRIOMethods 表中的函数之一。轮询方法的原型为
PRInt16 poll_method(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
轮询方法的目的是允许一层修改最终将在对底层网络传输的 select(或等效)函数的调用中使用的标志,并指示一层是否已经能够以轮询标志建议的方式取得进展。轮询方法的参数和返回值如下所述。
in_flags [输入参数]¶
in_flags 参数指定调用方感兴趣的 I/O 层堆栈**顶层**的事件。
对于 PR_Recv,您应该将 PR_POLL_READ 作为 in_flags 参数传递给轮询方法
对于 PR_Send,您应该将 PR_POLL_WRITE 作为 in_flags 参数传递给轮询方法
out_flags [输出参数]¶
如果一个 I/O 层准备在不涉及底层网络传输的情况下满足由 in_flags 定义的 I/O 请求,则其轮询方法在返回时设置 *out_flags 中的相应事件。
例如,考虑一个缓冲输入数据的 I/O 层。如果调用方希望测试读取就绪(即,在 in_flags 中设置了 PR_POLL_READ)并且该层缓冲了输入数据,则轮询方法将在 *out_flags 中设置 PR_POLL_READ 事件。它可以在不询问底层网络传输的情况下确定这一点。
PR_Poll(轮询方法的主要用户)的当前实现要求 *out_flags 中的事件反映调用方的视图。此要求可能会在将来的 NSPR 版本中放宽。为了保持与这种潜在的语义更改的兼容性,NSPR 客户端应该仅按以下如何使用轮询方法部分中所述使用 *out_flags。
返回值¶
如果轮询方法在 *out_flags 中存储非零值,则返回值将为 in_flags 的值。(注意:如果我们对上面提到的 *out_flags 进行语义更改,这可能会在将来的 NSPR 版本中更改。因此,NSPR 客户端应该仅按以下如何使用轮询方法部分中所述使用返回值。)如果轮询方法在 *out_flags 中存储零,则返回值将是底层关于 in_flags 的需求。这些是调用方应轮询底层网络传输的事件。对于某些协议,这些事件可能与 in_flags 中的事件(反映调用方的视图)不同。
如何使用轮询方法¶
轮询方法只能与以**非阻塞**模式的 NSPR 文件描述符一起使用。大多数 NSPR 客户端调用 PR_Poll 而不是直接调用轮询方法。但是,PR_Poll 只能与底层为 NSPR 参考实现的堆栈一起使用。如果您使用自己的底层实现,则必须按如下方式调用轮询方法。
声明两个 PRInt16 变量以接收轮询方法的返回值和 out_flags 输出参数。
PRInt16 new_flags, out_flags;
如果您要调用 PR_Recv,请将 PR_POLL_READ 作为 in_flags 参数传递。
new_flags = fd->methods->poll(fd, PR_POLL_READ, &out_flags);
如果您要调用 PR_Send,请将 PR_POLL_WRITE 作为 in_flags 参数传递。
new_flags = fd->methods->poll(fd, PR_POLL_WRITE, &out_flags);
如果您有兴趣在同一个文件描述符上同时调用 PR_Recv 和 PR_Send,请分别对轮询方法进行两次调用,一次将 PR_POLL_READ 作为 in_flags,另一次将 PR_POLL_WRITE 作为 in_flags,以便您知道网络传输层上的哪些事件分别映射到 PR_POLL_READ 和 PR_POLL_WRITE。
返回时,如果 (new_flags & out_flags) 非零,您可以立即尝试 PR_Recv 或 PR_Send。
否则 ((new_flags & out_flags) 为 0),您应该执行以下操作。
如果 new_flags 包含 PR_POLL_READ,则当底层网络传输可读时,您应该尝试 PR_Recv 或 PR_Send
如果 new_flags 包含 PR_POLL_WRITE,则当底层网络传输可写时,您应该尝试 PR_Recv 或 PR_Send
重要提示 不要以任何其他方式使用 out_flags,除了测试 (new_flags & out_flags) 是否为 0。这是 PR_Poll(主要用户,因此也是轮询方法的事实规范)使用 out_flags 的方式。