首页 > 代码库 > RFC1055:在串行线路上传输ip数据包的非标准协议

RFC1055:在串行线路上传输ip数据包的非标准协议

简介  

  TCP/IP协议族运行在各种各样的网络媒介上:IEEE 802.3(以太网)和802.5(令牌环)局域网、x.25线路、卫星线路、串行线路。给这些网络中的许多都定义了ip分组的标准格式,但是却没有用于串行线路的标准。SLIP(串行线路IP),目前已经成为事实上的标准,通常用在点对点串行连接上运行TCP/IP。它不是一个互联网标准,这份备忘录的发布不受限制。

历史

  SLIP起源于80年代早期的3COM UNET TCP/IP的实现,它仅仅是一个分组分帧协议:SLIP定义了一系列在串行线路上构造IP分组的字符,仅此而已。它不提供寻址、分组类型识别、错误检测/纠正或者压缩机制。因为这个协议所做的事很少,所以通常很容易实现。

  大约在1984年,Rick Adams为4.2 Berkeley Unix和Sun Microsystems工作站实现了SLIP并且向世界发布。它很快就因作为一种使用串行线路连接TCP/IP主机和路由器的简单可靠的方法而流行。

  SLIP通常用在专用串行链路,有时候也用在拨号网络,通常以1.2kbps到19.2kbps的线速被使用。它在主机和路由器混合连接时非常有用(主机-主机、主机-路由器、路由器-路由器都是SLIP网络的通用配置)。

 可用性

  SLIP对于大多数基于Berkeley Unix的系统都是可用的,并且被包括进Berkeley发布的4.3BSD标准版。SLIP可用于Ultrix、Sun Unix以及大多数其他衍生于Berkeley的Unix系统。有些终端集线器和IBM PC实现同样支持该协议。

  Berkeley Unix的SLIP可通过匿名ftp在uunet.uu.net的pub/s1.shar.Z获得,确保通过二进制模式传输该文件,并通过UNIX解压缩程序打开它,把获得的文件作为UNIX的/bin/sh(比如/bin/sh sl.shar)的shell命令使用。

协议

  SLIP协议定义了两个特殊字符:END和ESC。END是八进制的300(十进制192),ESC是八进制的333(十进制的219),不要把它和ASCII的ESCAPE字符混淆,为了讨论方便,ESC表示SLIP的ESC字符。发送分组时,SLIP主机简单地开始发送分组数据。如果一个数据字节和END字符相同,则用两个连续字节ESC和八进制334(十进制220)代替。如果存在和ESC字符相同的字节,则用两个连续字节ESC和八进制335(十进制221)代替。当分组的最后一个分组发送后,跟着发送一个END分组。

  Phil Karn建议对算法做一个简单的改变:和分组结尾一样,在开始也加上一个END字符,这样就能清除掉所有线路噪音引起的错误字节。通常情况下,接受者只会看到两个紧挨着的END字符,这样也就产生了一个无效的IP分组。如果SLIP实现没有丢弃这个长度为0的IP分组,IP实现必然会丢弃它。如果存在线路噪音,收到到的由线路噪音产生的数据将会被丢弃,而不会影响后面的分组。

  因为没有标准的SLIP规格,也就没有真正定义SLIP分组的最大长度。或许最好接受Berkeley UNIX SLIP驱动使用的最大分组长度:1006字节,包括IP头和传输头(不包括分帧字符)。因此,任何新的SLIP实现应该准备好接收1006字节数据报,并且不能发送超过1006字节的数据报。

缺陷

  有一些特性用户希望SLIP提供而它没有提供。公平地讲,SLIP只是一个很久以前设计的非常简单的协议,那时这些麻烦还不是真正的重要问题。下面是一些对现有SLIP协议一般能看到的确定:

   - 寻址:

    为了路由,SLIP链路两端的主机,都需要知道对方的IP地址。另外,当主机拨号连接到路由器时,地址可能是动态的,路由器可能需要将ip地址通告拨号主机,SLIP目前没有为主机提供在SLIP链接上传达地址信息的机制。

  - 类型识别:

    SLIP没有类型字段,因此,在一个SLIP连接上只能运行一个协议,在两台同时运行TCP/IP和DECnet的DEC主机的配置中,不可能在TCP/IP和DECnet之间,用SLIP分享同一条串行线路。SLIP是“串行线路IP”,如果一条串行连接两台多协议计算机,这些计算机可以在这条线路上使用多种协议。

  - 错误检测与纠正:

    嘈杂的电话线路可能会破坏分组的传输,因为线路速度可能很低(或许2400波特),重传分组的代价非常昂贵。错误检测在SLIP层并非绝对需要,因为任何IP应用应该检测被破坏的分组(IP头部、UDP和TCP校验和应该足够),但是,一些通用应用程序如NFS通常忽略校验和,依靠网络媒介去检测被破坏的分组。因为重传被线路噪音破坏的分组会花费很长时间,所以如果SLIP能提供某种它自己的简单错误检测机制,那将是非常有效。

  - 压缩:

    因为拨入线路太慢(通常2400bps),所以,分组压缩能给分组吞吐量带来极大提高。通常,在单独的TCP连接中的分组流,只有少数被改变的IP和TCP头部字段。所以,一个简单的压缩算法就是:只传输头部被改变的部分,而不是整个头部。

  为了设计和实现一个SLIP的继任者,不同的组做了很多工作,也许这个继任者能解决部分或者所有问题。

SLIP驱动程序

  下面的C语言函数发送和接收SLIP分组,它们依赖两个函数:send_char()和recv_char(),这两个函数用于在串行线路上发送和接收单个字符。

/* SLIP特殊字符编码

 */

#define END 0300 /* 分组结束标记 */
#define ESC 0333 /* 填充标记 */
#define ESC_END 0334 /* ESC ESC_END表示END数据字段 */
#define ESC_ESC 0335 /* ESC ESC_ESC表示ESC数据字段 */

 

/* SEND_PACKET:发送长度为len的分组,起始位置为p

 */

void send_packet(p, len)
    char *p;
    int len; {
  /* 发送一个初始END字符,清除所有因为线路噪音而在接受者那里累积的数据
  */
  send_char(END);
  /* 为分组中的每一个字节发送适当的字符序列
  */
  while(len--) {
    switch(*p) {
    /* 如果是一个END字符,我们发送一个特殊的两字符编码, 

     * 这样,接收者就不会以为我们发送了一个END字符
     */
    case END:
      send_char(ESC);
      send_char(ESC_END);
      break;
    /* 如果是一个ESC字符,我们发送一个特殊的两字符编码,

     * 这样,接收者就不会以为我们发送了一个ESC字符。
     */
    case ESC:
      send_char(ESC);
      send_char(ESC_ESC);
      break;
    /* 其他情况,直接发送字符
     */
    default:
      send_char(*p);
    }
    p++;
  }
  /* 告诉接收者,我们完成了一个分组的发送
  */
  send_char(END);
}

 

/* RECV_PACKET:接收一个分组并放入p指向的缓冲区,如果接收的长度大于len,分组将被截断。返回缓冲区中存储的字节的数目

 */

int recv_packet(p, len)
    char *p;
    int len; {
  char c;
  int received = 0;
  /* 循环读取字节,直到接收完整个分组
   * 确保用完缓冲区后不再复制
   */
  while(1) {
    /* 取一个字符来处理
     */
    c = recv_char();
    /* 在需要时处理填充
     */
    switch(c) {
    /* 如果是END字符,表示分组处理完成
     */
    case END:
    /* 小优化:如果分组中没有数据,则忽略它。

     * 这是为了避免用双END字符生成的空分组打扰IP,

     * 这些双END字符是为了探测线路噪音。
     */
      if(received)
        return received;
      else
        break;
    /* 如果是一个ESC字符,等待接收另外一个字符,然后推断出将要存入分组的字符
    */
    case ESC:
      c = recv_char();
      /* 如果c不是两个字符中的一个,就违反了协议

       * 最好是将这个字符填充进分组
       */
      switch(c) {
      case ESC_END:
        c = END;
        break;
      case ESC_ESC:
        c = ESC;
        break;
      }
    /* 这里是默认处理,直接保存字符
    */
    default:
      if(received < len)
        p[received++] = c;
    }
  }
}

RFC1055:在串行线路上传输ip数据包的非标准协议