簡介
TCP/IP協議組運行在各種各樣的網絡媒介上:IEEE802.3(以太網)和802.5(令牌環)局域網(LAN)、X.25線路、衛星鏈路以及串行線路。其中許多網絡已經有IP分組的標準封裝格式,但沒有用于串行線路的標準。SLIP(串行線路IP)目前已成為事實上的標準,廣泛地用于在點對點串行連接上運行TCP/IP。這并不是一個Inte.net標準,本備忘錄的發布不受限制。
歷史(HISTORY)
SLIP源于80年代初期的3COMUNETTCP/IP實現。SLIP只是一個分組分幀協議,僅僅定義了一系列在串行線路上構造IP分組的字符。它沒有提供地址、分組類型標識、錯誤檢查/修正或者壓縮機制。因為這個協議所作的工作這么少,通常很容易實現。
大約在1984年,RickAdam為4.2BerkeleyUnix和SunMicrosystem工作站實現了SLIP并公之于眾,并作為一種使用串行線路連接TCP/IP主機和路由器的簡單可靠的方法很快流行起來。
SLIP通常專門用于串行連接,有時候也用于撥號網絡,使用的線路速率一般介于1200bps和19.2Kbps之間。SLIP允許主機和路由器混合連接(主機-主機、主機-路由器、路由器-路由器都是SLIP網絡通用的配置),因而非常有用。
可用性(AVAILABILITY)
SLIP可用于大多數基于BerkeleyUNIX的系統,并且被包括進了Berkeley的4.3BSD標準版。SLIP可用于Ultrix、SunUNIX和大多數派生自Berkeley的UNIX系統。一些終端集線器和IBMPC的實現也支持該協議。
BerkeleyUNIX的SLIP可以使用匿名FTP從uunet.uu.net上的pub/sl.shar.Z中獲得。確保傳輸的是二進制文件,并使用UNIX解壓程序打開它,然后把解開的文件作為UNIX/bin/sh(如/bin/shsl.shar)的SHELL命令使用
協議(PROTOCOL)
SLIP定義了兩個特殊字符:END和ESC。END是八進制的300(十進制192),ESC不同與ASCII的ESCAPE字符,是八進制的333(十進制219),本文中的ESC指的是SLIPESC字符。發送分組時,SLIP主機只是簡單地發送分組數據。如果數據中有一個字節與END字符的編碼相同,就連續傳輸兩個字節ESC和八進制的334(十進制220)代替它。如果與ESC字符相同,就連續傳輸兩個字節ESC和八進制的335(十進制221)代替它。分組的最后一個字節發出后,再傳送一個END字符。
PhilKarn建議稍微修改一下這個算法,分組的開始以及結束都使用END字符,這樣可以刷掉線路噪聲造成的不正確的字節。一般情況下接收方將只看到兩個緊挨著的END字符并生成一個壞的IP分組。如果SLIP實現沒有丟棄長度為0的IP分組,IP實現就應該丟棄。如果存在線路噪聲,接收到的由線路噪聲造成的數據將被丟棄,而不會影響后續的分組。
因為沒有“標準的”SLIP規范,也就沒有SLIP分組最大長度的實際定義??赡茏詈檬墙邮蹷erkeleyUNIXSLIP驅動程序使用的最大分組長度:1006字節,其中包括IP頭和傳輸協議頭,但不含分幀字符。這樣任何新的SLIP實現都應能夠接收1006字節的數據報,在一個數據報內發送的字節數不應超過1006。
缺陷(DEFICIENCIES)
有幾種特性使許多用戶希望SLIP提供而沒有提供的。公平的講,SLIP只是一個很久以前設計的非常簡單的協議,而在當時這些問題還并不真正重要。下面是對現有SLIP協議一般認識到的缺陷:
地址:
SLIP連接的兩臺計算機都必須知道對方的IP地址才能傳輸。另外,在主機使用SLIP撥號連接一個路由器時,地址設置可能隨時變化,路由器可能需要通知撥號主機IP地址的變更。SLIP目前沒有為主機提供通過SLIP連接交換地址信息的機制。
類型標識:
SLIP沒有類型字段。因此在一個SLIP連接上只能運行一個協議,即使在兩臺運行TCP/IP和DECnet的DEC計算機的配置中,如果使用SLIP,也不可能讓TCP/IP和DECnet同時使用一條連接兩者的串行線路。因為SLIP是“串行線路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<len)
p[received++]=c;
}
}
}