系统调用与控制命令
这里我们概述建立、切换和断开连接的机制。如上所述, NCP 通过系统调用与用户进程交互, 并通过控制命令与其他 NCP 交互。因此, 我们先给出系统调用和控制命令的部分描述。
系统调用因操作系统而异, 因此以下描述仅供参考。这里我们假设一个进程有若干条输入输出路径, 我们称之为端口。每个端口可以连接到一个顺序 I/O 设备, 并且在连接期间只在一个方向上传输信息。我们还假设在传输进行期间进程处于阻塞 (被挂起、睡眠) 状态。以下是系统调用列表:
Init <port>, <AEN 1>, <AEN 2>, <foreign socket>
where <port> is part of the process issuing the Init
_
<AEN 1> |
and +- are 8-bit AEN's (see Figure 2)
<AEN 2> |
_|
第一个 AEN 用于发起连接; 第二个在连接存在期间使用。
<foreign socket> 是连接远端的 40 位 socket 名称。
<AEN 1> 和 <AEN 2> 的低位比特必须一致, 而且它们必须是 <foreign socket> 低位比特的补码。
NCP 把 <AEN 1> 和 <AEN 2> 分别与进程的用户编号和主机编号拼接起来, 构成 40 位的 socket。然后它向远端 NCP 发送一条请求连接 (Request for Connection, RFC) 控制命令。当远端 NCP 作出肯定响应时, 连接即建立, 进程被解除阻塞。如果远端 NCP 作出否定响应, 本地 NCP 会解除请求进程的阻塞, 但告知它该系统调用已失败。
Listen <port>, <AEN 1>
其中 <port> 和 <AEN 1> 同上。NCP 保留这些端口和 <AEN 1>, 并阻塞该进程。当一条指名本地 socket 的 RFC 控制命令到达时, 进程被解除阻塞, 并被告知有一个外部进程正在呼叫。
Accept <AEN 2>
在一次 Listen 被满足之后, 进程可以拒绝该呼叫, 也可以接受它并把它切换到另一个 socket。为了接受呼叫, 进程发出 Accept 系统调用。NCP 随后发回一条 RFC 控制命令。
Close <port>
建立连接之后, 进程发出 Close 以断开连接。在 Listen 之后为拒绝呼叫也会发出 Close。
Transmit <port>, <addr>
如果 <port> 连接到发送 socket, 则 <addr> 指向一条要发送的消息。该消息前面带有以位计的长度。
如果 <port> 连接到接收 socket, 则消息存储在 <addr> 处。消息的长度先被存储。
控制命令
已经定义了一套控制命令词汇表, 用于网络控制程序之间的通信。每条控制命令由一个 8 位的操作码 (用以表明其功能) 后跟若干参数组成。每个操作码的参数数量和格式都是固定的。发往某一主机的控制命令序列可以打包进单条控制消息。
RFC <my socket 1>, <my socket 2>.
<your socket>, (<link>)
发送这条命令是因为某个进程执行了 Init 系统调用或 Accept 系统调用。链路由预期接收方分配, 因此如果 <my socket 1> 是发送 socket, 就省略它。
用相同的命令既发起连接 (Init) 又接受呼叫 (Accept) 有明显的优势。如果响应命令与发起命令不同, 那么两个进程可能互相呼叫, 并因等待对方响应而双双阻塞。采用这一方案则不会发生死锁, 并且它提供了一种更紧凑的方式来连接一组进程。
CLS <my socket>, <your socket>
指定的连接被终止
CEASE <link>
当接收进程消费输入的速度赶不上输入到达的速度时, 接收主机中的缓冲空间被用来排队等待中的消息。由于通常只有有限的空间可用, 接收主机可能需要禁止发送主机在这条有问题的连接上再发送任何消息。当发送主机收到这条命令时, 它可以阻塞产生这些消息的进程。
RESUME <link>
这条命令同样从接收主机发往发送主机, 并取消先前的一条 CEASE。