• 协议的分用以及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详解
  • 相关阅读:
    C#执行异步操作的几种方式
    spring boot swagger ui使用 nginx 部署后无法使用问题
    PHP支付宝接口RSA验证
    认证加密算法php hash_hmac和java hmacSha1的问题
    如何实现从 Redis 中订阅消息转发到 WebSocket 客户端
    ffmpeg安装
    nginx静态资源反向代理
    Redis基础知识 之——发布/订阅
    linux下安装git
    php实现无限级分类查询(递归、非递归)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3308958.html
Copyright © 2020-2023  润新知