協議的分用以及wireshark對協議的識別


協議的分用以及wireshark對協議的識別

    在TCP/IP詳解一書中談到了協議的分用,書中的圖1-8如上。圖1-8可以很好地解釋在互聯網的分層結構中,底層的協議頭是如何承載上層的不同的協議的。對於鏈路層而言,以太網首部中有不同幀類型用於表示以太網幀內的數據。在IP數據包的首部,也有專門的8位協議類型,用於表示IP包中的上層協議類型,網址http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml中給出了IETF規定的詳細的協議類型號,其中TCP是6,UDP是17,ICMP是1。不過在傳輸層的兩個常用協議TCP和UDP首部中,並沒有協議類型的字段,TCP和UDP包內的應用程協議的類型依靠的是TCP和UDP包首部的端口號來進行區分。對於一些常用的應用層協議IETF都規定了相應的熟知端口號,在網址http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml中有一份詳細的列表。TCP和UDP報頭的16比特端口號給應用層協議的設計提供了足夠的設計空間(65535個)和足夠的靈活度。

   理解了協議的分用之后,就比較容易理解wireshark是如何將數據包識別和展示出來的了。wireshark的工作原理的簡單介紹可以參見http://gaia.cs.umass.edu/wireshark-labs/Wireshark_Intro_v6.0.pdf。概括地說,就是wireshark是一款建立在已有的包捕捉工具上的一款數據包分析軟件。常見的抓包的庫有libpcap、jpcap、winpcap等等,這些抓包工具將主機的網卡設置為混雜模式,從而可以捕捉到目的MAC不是主機網卡的數據包。而wireshark基於這些庫捕捉到的包進行識別和分析,將包中內容按照協議類型和層次展示出來。

  不過對於那些不采用熟知端口傳輸的應用層協議而言,wireshark就有可能出現無法識別的情況,這也是我最近遇到的一個場景。我在抓包的時候遇見了wireshark protocol一欄顯示enttec,Info 一欄顯示 unknown的情況。經過一段時間的分析,可以確定wireshark顯示enttec和unknown的原因是TCP采用了非熟知端口發送HTTP報文。不過wireshark在設計中已經考慮到這樣一種情況的出現,可以針對非熟知端口的已知應用層協議設置相應的解碼方式。具體的方法是:選中無法識別的報文->右鍵單擊->Decode As->選擇相應的應用層協議。

  

 
 

JavaScript 繼承

 

初學面向對象的時候總會背面向對象三個特征——封裝、繼承和多態,生怕考試或面試時自己答不上來。習慣於從C++、Java、C#的角度看待繼承,工作后用到JavaScript覺得這種東西不會有繼承,因為JavaScript沒有強類型,怎么繼承。

弱類型實現繼承的理論可行性

“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。”

基礎弱類型語言多了就會漸漸聽說鴨子類型(duck typing),在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實現特定的接口,而是由當前方法和屬性的集合決定的,在鴨子類型中,關注的不是對象的類型本身,而是它是如何使用的。通俗來說一個對象如果擁有某個對象的方法和屬性,就可以看作是這個對象。

JavaScript 繼承實現原理

根據duck typing的理論,在JavaScript中如果對象subType包含了superType的屬性和方法,就可以認為其繼承了superType。在JavaScript將原型鏈作為實現繼承的主要方法。基本原理是利用原型讓一個subType引用superType的屬性和方法。如果對原型不是很了解可以看看JavaScript prototype,可以將subType的prototype屬性設為superType的實例,這時候subType的原型鏈中就包含了superType的屬性和方法,大致是這樣的

復制代碼
function SuperType(){
        this.property=true;
        }

    SuperType.prototype.getSuperValue=function(){
        return this.property;
        };

    function SubType(){
        this.subProperty=false;
        }

    SubType.prototype=new SuperType();

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }
復制代碼

這樣SubType就實現了對SuperType的繼承,看個圖

image

驗證一下,是不是這個樣子

var instance=new SubType();
    console.log(instance.getSuperValue()); //true
    console.log(instance.getSubValue()); //false
    console.log(instance instanceof SuperType); //true
    console.log(instance instanceof SubType); //true

果不其然,SubType的實例同時也是SuperType的實例,可以訪問到SuperType的屬性和方法,根據duck typing這就實現了SubType對SuperType的繼承。在上面的代碼中SubType沒有使用其默認的prototype對象,而是使用了SuperType的實例,這樣SubType的實例擁有

1.SuperType實例的屬性和方法

2.SuperType的prototype的屬性和方法(如上圖,在原型鏈中SuperType的實例有指向SuperType的prototype的指針)

3.SubType實例屬性和方法(subProperty)

4.SubType新的prototype對象追加的屬性和方法(getSubValue)

熟悉JavaScript的同學肯定清楚:和很多強類型面向對象語言一樣,JavaScript的所有引用類型都默認繼承與Object對象,這個繼承也是通過原型鏈實現的。

image

所有函數都是Object對象的實例,這樣是不是明白了為什么所有自定義類型都會用於toString, valueOf 等默認方法了吧,看起來很不錯,但是這樣的繼承方式有兩個需要注意的地方

1.給子類型的prototype對象內追加方法和屬性必須在繼承了父類型實例之后,否則追加的方法、屬性會被重寫,也就是說上面的例子

復制代碼
function SubType(){
        this.subProperty=false;
        }

    SubType.prototype=new SuperType();

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }
復制代碼

不能寫成這樣

復制代碼
function SubType(){
        this.subProperty=false;
        }

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }
    
    SubType.prototype=new SuperType();
復制代碼

2.子類型的prototype不能通過字面量賦值,這樣也會重寫原型鏈而不是追加,也就是說不能寫成這樣

復制代碼
function SubType(){
        this.subProperty=false;
        }

    SubType.prototype=new SuperType();

    SubType.prototype={
        getSubValue:function(){
            return this.subProperty;
        }
    }
復制代碼

組合繼承

聰明的同學可能已經按捺不住要質問了,這樣的做法當父類型中存在引用類型的屬性的時候,子類型所有實例不是都共享這個屬性了嗎!

復制代碼
function SuperType(){
        this.property=true;
        this.colors=['red','blue','green'];
        }

    SuperType.prototype.getSuperValue=function(){
        return this.property;
        };

    function SubType(){
        this.subProperty=false;
        }

    SubType.prototype=new SuperType();

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }

    var sub1=new SubType();
    sub1.colors.push('yellow');
    var sub2=new SubType();
    console.log(sub2.colors);//["red", "blue", "green", "yellow"]
復制代碼

確實是這樣的,但是這個錯誤很熟悉的趕腳有沒有,在JavaScript創建對象中也面臨這個問題,使用構造函數可以使實例擁有自己獨有的屬性,問題就可以迎刃而解了

復制代碼
function SuperType(){
        this.property=true;
        this.colors=['red','blue','green'];
        }

    SuperType.prototype.getSuperValue=function(){
        return this.property;
        };

    function SubType(){
        this.subProperty=false;
        SuperType.call(this);
        }
 SubType.prototype=new SuperType(); 
    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }

    var sub1=new SubType();
    sub1.colors.push('yellow');
    var sub2=new SubType();
    console.log(sub2.colors);//["red", "blue", "green"]
復制代碼

這樣在子類的構造函數中調用父類的構造函數,這樣的寫法實際上是在新創建的SubType的實例環境下調用SuperType的構造函數,實例中執行SuperType函數中對象初始化代碼,Subtype的每個實例就會有自己的colors副本了。這樣的繼承方式在坊間被稱為組合式繼承。

這樣做還多了個好處,可以傳遞參數了

復制代碼
function SuperType(name){
        this.property=name;
        this.colors=['red','blue','green'];
        }

    SuperType.prototype.getSuperValue=function(){
        return this.property;
        };

    function SubType(name){
        this.subProperty=false;
        SuperType.call(this,name);
        }
 SubType.prototype=new SuperType(); 
    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }

    var sub1=new SubType('Byron');
    console.log(sub1.property);//Byron
復制代碼

寄生組合式繼承

看起來使用組合式繼承很完美了,但是總是有但是,使用組合繼承總會調用兩次父類的構造函數,這樣父類的實例屬性和方法在子類的實例中會有兩份。

復制代碼
function SubType(name){
        this.subProperty=false;
        SuperType.call(this,name); //第一次
        }

    SubType.prototype=new SuperType(); //第二次

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }
復制代碼

image

問題的根源就是調用兩次SuperType的構造函數,其實在第一次調用的時候SubType就已經獲得了SuperType的實例屬性和方法,第二次調用的時候僅需要SuperType的prototype屬性就可以了,因此可以這樣寫

復制代碼
function extend(subType,superType){
    var _prototype=new Object(superType.prototype); //得到父類prototype對象副本
    _prototype.constructor=subType; //constructor屬性改為子類自己的
    subType.prototype=_prototype; //重寫子類prototype
}

    function SuperType(name){
        this.property=name;
        this.colors=['red','blue','green'];
        }

    SuperType.prototype.getSuperValue=function(){
        return this.property;
        };

    function SubType(name){
        this.subProperty=false;
        SuperType.call(this,name); 
        }

    extend(SubType,SuperType);

    SubType.prototype.getSubValue=function(){
        return this.subProperty;
        }
復制代碼

image

這樣看起來不錯了吧

 
 
分類:  JavaScript
分類:  計算機網絡
標簽:  TCP/IP詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM