JavaScript is required to for searching.
跳过导航链接
退出打印视图
编程接口指南     Oracle Solaris 10 1/13 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  内存和 CPU 管理

2.  用于 Solaris Cluster 的远程共享内存 API

3.  会话描述协议 API

4.  进程调度程序

5.  地址组 API

6.  输入/输出接口

7.  进程间通信

8.  套接字接口

9.  使用 XTI 和 TLI 编程

什么是 XTI 和 TLI?

XTI/TLI 读/写接口

写入数据

读取数据

关闭连接

高级 XTI/TLI 主题

异步执行模式

高级 XTI/TLI 编程示例

异步联网

联网编程模型

异步无连接模式服务

使端点异步

异步网络传输

异步连接模式服务

异步建立连接

异步使用连接

异步打开

传输文件描述符

状态转换

XTI/TLI 状态

传出事件

传入事件

状态表

协议独立性准则

XTI/TLI 与套接字接口

套接字到 XTI/TLI 的等效项

XTI 接口的附加功能

10.  包过滤钩子

11.  传输选择和名称到地址映射

12.  实时编程和管理

13.  Solaris ABI 和 ABI 工具

A.  UNIX 域套接字

索引

异步联网

本节讨论了针对实时应用程序使用 XTI/TLI 进行异步网络通信的技术。SunOS 平台使用 STREAMS 异步功能和 XTI/TLI 库例程非阻塞模式的组合来提供对 XTI/TLI 事件的异步网络处理的支持。

联网编程模型

与文件和设备 I/O 类似,网络传输可以通过进程服务请求以同步或异步方式完成。

同步联网的执行方式与同步文件和设备 I/O 类似。与 write(2) 接口类似,发送请求会在缓冲消息之后返回,但是如果缓冲区不立即可用,则可能暂停调用过程。与 read(2) 接口类似,接收请求在数据到达以满足请求之前会暂停执行调用过程。由于不存在针对传输服务的保证绑定,因此同步联网不适用于必须具有与其他设备相关的实时行为的进程。

异步联网通过非阻塞服务请求提供。此外,可能建立连接时,可能发送数据时,或可能接收数据时,应用程序可以请求异步通知。

异步无连接模式服务

通过在传输数据时针对非阻塞服务配置端点,以及针对异步通知轮询或接收异步通知来执行异步无连接模式联网。如果使用异步通知,则通常在信号处理程序中执行数据的实际接收。

使端点异步

使用 t_open(3NSL) 建立端点,并使用 t_bind(3NSL) 建立其标识之后,可以针对异步服务配置该端点。使用 fcntl(2) 接口在端点上设置 O_NONBLOCK 标志。这样,无立即可用缓冲区的 t_sndudata(3NSL) 调用将返回 -1,且 t_errno 设置为 TFLOW。同样,无可用数据的 t_rcvudata(3NSL) 调用将返回 -1,且 t_errno 设置为 TNODATA

异步网络传输

虽然应用程序可以使用 poll(2) 来定期检查数据是否到达或等待在端点上接收数据,但是可能需要在数据到达时接收异步通知。结合使用 ioctl(2)I_SETSIG 命令可请求在端点收到数据时将 SIGPOLL 信号发送到该进程。应用程序应检查多条消息导致单个信号的可能性。

在以下示例中,protocol 为应用程序选择的传输协议的名称。

#include <sys/types.h>
#include <tiuser.h>
#include <signal.h>
#include <stropts.h>

int              fd;
struct t_bind    *bind;
void             sigpoll(int);

    fd = t_open(protocol, O_RDWR, (struct t_info *) NULL);

    bind = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
    ...     /* set up binding address */
    t_bind(fd, bind, bin

    /* make endpoint non-blocking */
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);

    /* establish signal handler for SIGPOLL */
    signal(SIGPOLL, sigpoll);

    /* request SIGPOLL signal when receive data is available */
    ioctl(fd, I_SETSIG, S_INPUT | S_HIPRI);

    ...

void sigpoll(int sig)
{
    int                  flags;
    struct t_unitdata    ud;

    for (;;) {
        ... /* initialize ud */
        if (t_rcvudata(fd, &ud, &flags) < 0) {
            if (t_errno == TNODATA)
                break;  /* no more messages */
            ... /* process other error conditions */
    }
    ... /* process message in ud */
}

异步连接模式服务

对于连接模式服务,应用程序不仅可以安排数据传输,还可以对异步完成的连接建立本身进行安排。操作顺序取决于该进程是尝试连接到其他进程还是等待连接尝试。

异步建立连接

进程可以尝试某个连接并异步完成该连接。进程将首先创建连接端点,然后使用 fcntl(2) 针对非阻塞操作配置该端点。与无连接数据传输一样,还可以针对连接完成时的异步通知和后续数据传输来配置该端点。然后,连接进程将使用 t_connect(3NSL) 开始进行传输设置。随后将使用 t_rcvconnect(3NSL) 来确认连接的建立。

异步使用连接

要异步等待连接,进程首先要建立一个绑定到服务地址的非阻塞端点。当 poll(2) 的结果或异步通知指示连接请求到达时,该进程可以使用 t_listen(3NSL) 来获取连接请求。要接受该连接,进程可以使用 t_accept(3NSL)。必须针对异步数据传输分别配置响应端点。

以下示例说明如何异步请求连接。

#include <tiuser.h>
int             fd;
struct t_call   *call;

fd = /* establish a non-blocking endpoint */

call = (struct t_call *) t_alloc(fd, T_CALL, T_ADDR);
/* initialize call structure */
t_connect(fd, call, call);

/* connection request is now proceeding asynchronously */

/* receive indication that connection has been accepted */
t_rcvconnect(fd, &call);

以下示例说明如何异步侦听连接。

#include <tiuser.h>
int             fd, res_fd;
struct t_call   call;

fd = /* establish non-blocking endpoint */

/*receive indication that connection request has arrived */
call = (struct t_call *) t_alloc(fd, T_CALL, T_ALL);
t_listen(fd, &call);

/* determine whether or not to accept connection */
res_fd = /* establish non-blocking endpoint for response */
t_accept(fd, res_fd, call);

异步打开

有时,可能要求应用程序动态打开从远程主机挂载的文件系统中的常规文件,或者其初始化可能延迟的设备上的常规文件。但是,正在处理此类打开文件的请求的同时,应用程序不能实现对其他事件的实时响应。SunOS 软件通过以下方法解决了此问题:让另一个进程处理文件的实际打开操作,然后将文件描述符传递到实时进程。

传输文件描述符

SunOS 平台提供的 STREAMS 接口提供了一种将开放式文件描述符从一个进程传递到另一个进程的机制。带有开放式文件描述符的进程使用带有命令参数 I_SENDFDioctl(2)。另一个进程通过调用带有命令参数 I_RECVFDioctl(2) 来获取文件描述符。

在以下示例中,父进程输出有关测试文件的信息,并创建一个管道。接下来,进程会创建一个子进程,该子进程可打开该测试文件并通过管道将开放式文件描述符传递回父进程。随后父进程会显示关于新文件描述符的状态信息。

示例 9-6 文件描述符传送

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <stdio.h>

#define TESTFILE "/dev/null"
main(int argc, char *argv[])
{
    int fd;
    int pipefd[2];
    struct stat statbuf;

    stat(TESTFILE, &statbuf);
    statout(TESTFILE, &statbuf);
    pipe(pipefd);
    if (fork() == 0) {
        close(pipefd[0]);
        sendfd(pipefd[1]);
    } else {
        close(pipefd[1])
        recvfd(pipefd[0]);
    }
}

sendfd(int p)
{
    int tfd;

    tfd = open(TESTFILE, O_RDWR);
    ioctl(p, I_SENDFD, tfd);
}

recvfd(int p)
{
    struct strrecvfd rfdbuf;
    struct stat statbuf;
    char            fdbuf[32];

    ioctl(p, I_RECVFD, &rfdbuf);
    fstat(rfdbuf.fd, &statbuf);
    sprintf(fdbuf, "recvfd=%d", rfdbuf.fd);
    statout(fdbuf, &statbuf);    
}

statout(char *f, struct stat *s)
{
    printf("stat: from=%s mode=0%o, ino=%ld, dev=%lx, rdev=%lx\n",
        f, s->st_mode, s->st_ino, s->st_dev, s->st_rdev);
    fflush(stdout);
}