在串行线路上传输IP数据报的非标准协议( 二 )


错误检测/修正:
嘈杂的电话线路可能破坏传输中的分组 。因为线路速率可能很低(或许是2400波特),重新传输分组的代价很高 。错误检测在SLIP层并非绝对需要,因为IP应用程序可以发现损坏的分组(IP头部与TCP和UDP的校验和就可以满足),但是一些通用程序如NFS通常忽略校验和而依靠网络媒介检测损坏的分组 。因为重新传输被线路噪声破坏的分组需要很长时间,假如自身能够提供某种简单的纠错机制就可以改善SLIP的效率 。
压缩:
拨号线路非常慢(通常是2400bps),分组压缩可以大幅提高分组的吞吐量 。通常单纯的TCP连接分组流在IP和TCP头部有几个很少变动的字段,因而可以使用一种简单的压缩算法只发送头部变化的部分而不是整个头部 。
围绕着SLIP后继者的设计与实现,几个不同的团体已经做了一些工作,可能会部分或者全部解决这些问题 。
SLIP驱动程序(SLIPDRIVERS)
下面的C语言函数发送并接收SLIP分组 。它们依靠于send_char()和recv_char(),这两个函数在串行线路上发送和接收单个字符 。
/*SLIP非凡字符编码
*/
#defineEND0300/*分组结束标记*/
#defineESC0333/*填充字节标记*/
#defineESC_END0334/*ESCESC_END表示数据字节END*/
#defineESC_ESC0335/*ESCESC_ESC表示数据字节ESC*/
/*SEND_PACKET:发送长“len”的分组,起始位置为“p”*/
voidsend_packet(p,len)
char*p;
intlen;{
/*发送一个初始END字符,清除由于线路噪声可能堆积在接收方的任何数据
*/
send_char(END);
/*为分组中的每个字符发送适当的字符序列
*/
while(len--){
switch(*p){
/*假如与END字符相同,我们就发送
*两个非凡字符码避免接受方认为
*我们发出了END结束标记
*/
caseEND:
send_char(ESC);
send_char(ESC_END);
break;
/*假如与ESC字符编码相同,
*我们就发送两个非凡字符码
*避免接受方以为我们发送了ESC
*/
caseESC:
send_char(ESC);
send_char(ESC_ESC);
break;
/*否则,我们就发送字符本身
*/
default:
send_char(*p);
}
p;
}
/*告诉接收方我们已经完成分组的发送
*/
send_char(END);
}
/*RECV_PACKET:接收分组并放入地址为“p”的缓冲区,
*假如收到的字节数大于len,分组将被截断
*返回保存在缓冲区的字节数
*/
intrecv_packet(p,len)
char*p;
intlen;{
charc;
intreceived=0;
/*使用循环读取字节直到接受完整个分组
*假如用完缓冲区就不再复制
*/
while(1){
/*取一个字符进行处理
*/
c=recv_char();
/*假如需要则处理填充字符
*/
switch(c){
/*假如是END字符就表示分组完成
*/
caseEND:
/*一点小小的改进:假如分组没有数据则忽略掉 。
*这意味着避免双END字符构成的空分组打搅IP,
*这种空分组用于检测线路噪声 。
*/
if(received)
returnreceived;
else
break;
/*假如收到ESC字符,则等待
*下一个字符来决定把什么字符存入分组
*/
caseESC:
c=recv_char();
/*假如“c”不是这两个字符中的一个,
*就违反了协议 。最好的办法似乎是
*单独保留这个字符并填入分组
*/
switch(c){
caseESC_END:
c=END;
break;
caseESC_ESC:
c=ESC;
break;
}
/*现在到了缺省处理情况,就让它保存字符
*/
default:
if(received p[received]=c;
}
}
}

推荐阅读