精华内容
下载资源
问答
  • IOC和DI本质理解

    千次阅读 2016-08-04 13:29:50
    【4】迪米特法则(最少知识原则):不知道依赖的具体实现,只知道需要提供某类服务的对象(面向抽象编程),松散耦合,一个对象应当其他对象有尽可能少的了解,不和陌生人(实现)说话 【5】IoC是一种让服务消费...

    IoC

     

    IoC: Inversion of Control,控制反转, 控制权从应用程序转移到框架(如IoC容器),是框架共有特性

     

    1、为什么需要IoC容器
    1.1、应用程序主动控制对象的实例化及依赖装配 
    Java代码   收藏代码
    1. A a = new AImpl();  
    2. B b = new BImpl();  
    3. a.setB(b);  
    本质:创建对象,主动实例化,直接获取依赖,主动装配 
    缺点:更换实现需要重新编译源代码
               很难更换实现、难于测试
               耦合实例生产者和实例消费者 

    Java代码   收藏代码
    1. A a = AFactory.createA();  
    2. B b = BFactory.createB();  
    3. a.setB(b);  
     
    本质:创建对象,被动实例化,间接获取依赖,主动装配  (简单工厂) 
    缺点:更换实现需要重新编译源代码
               很难更换实现、难于测试


    Java代码   收藏代码
    1. A a = Factory.create(“a”);  
    2. B b = Factory.create(“b”);  
    3. a.setB(b);   

      <!—配置.properties-->
    Xml代码   收藏代码
    1. a=AImpl  
    2. b=BImpl  
     
    本质:创建对象,被动实例化,间接获取依赖, 主动装配
            (工厂+反射+properties配置文件、
               Service Locator、注册表) 
    缺点:冗余的依赖装配逻辑


    我想直接:
        //返回装配好的a
    Java代码   收藏代码
    1. A a = Factory.create(“a”);   

                  
    1.2、可配置通用工厂:工厂主动控制,应用程序被动接受,控制权从应用程序转移到工厂
    Java代码   收藏代码
    1. //返回装配好的a   
    2. A a = Factory.create(“a”);  
       <!—配置文件-->
    Java代码   收藏代码
    1. <bean id=“a” class=“AImpl”>  
    2.     <property name=“b” ref=“b”/>  
    3. </bean>  
    4. <bean id=“b” class=“BImpl”/>  
     本质:创建对象和装配对象, 
              被动实例化,被动接受依赖,被动装配
            (工厂+反射+xml配置文件)
    缺点:不通用

    步骤:
    1、读取配置文件根据配置文件通过反射
    创建AImpl
    2、发现A需要一个类型为B的属性b
    3、到工厂中找名为b的对象,发现没有,读取
    配置文件通过反射创建BImpl
    4、将b对象装配到a对象的b属性上
    【组件的配置与使用分离开(解耦、更改实现无需修改源代码、易于更好实现) 】

    1.3、 IoC(控制反转)容器:容器主动控制
    Java代码   收藏代码
    1. //返回装配好的a   
    2. A a = ApplicationContext.getBean(“a”);  
     <!—配置文件-->
    Java代码   收藏代码
    1. <bean id=“a” class=“AImpl”>  
    2.     <property name=“b” ref=“b”/>  
    3. </bean>  
    4. <bean id=“b” class=“BImpl”/>  
     
    本质:创建对象和装配对象、管理对象生命周期
              被动实例化,被动接受依赖,被动装配
            (工厂+反射+xml配置文件)
    通用 


     

    IoC容器:实现了IoC思想的容器就是IoC容器

    2、IoC容器特点
    【1】无需主动new对象;而是描述对象应该如何被创建即可
              IoC容器帮你创建,即被动实例化;
    【2】不需要主动装配对象之间的依赖关系,而是描述需要哪个服务(组件),
             IoC容器会帮你装配(即负责将它们关联在一起),被动接受装配;
    【3】主动变被动,好莱坞法则:别打电话给我们,我们会打给你;
    【4】迪米特法则(最少知识原则):不知道依赖的具体实现,只知道需要提供某类服务的对象(面向抽象编程),松散耦合,一个对象应当对其他对象有尽可能少的了解,不和陌生人(实现)说话
    【5】IoC是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。

    3、理解IoC容器问题关键:控制的哪些方面被反转了?
    1、谁控制谁?为什么叫反转? ------  IoC容器控制,而以前是应用程序控制,所以叫反转 
    2、控制什么?               ------  控制应用程序所需要的资源(对象、文件 ……
    3、为什么控制?             ------  解耦组件之间的关系 
    4、控制的哪些方面被反转了? ------  程序的控制权发生了反转:从应用程序转移到了IoC容器。 

    思考:
        1: IoC/DI等同于工厂吗?
        2: IoC/DI跟以前的方式有什么不一样?
    领会: 主从换位的思想

     

    4、实现了IoC思想的容器就是轻量级容器吗?
    如果仅仅因为使用了控制反转就认为这些轻量级容器与众不同,就好象在说我的轿车与众不同因为它有四个轮子? 

    容器:提供组件运行环境,管理组件声明周期(不管组件如何创建的以及组件之间关系如何装配的);

    IoC容器不仅仅具有容器的功能,而且还具有一些其他特性---如依赖装配
                 
    控制反转概念太广泛,让人迷惑,后来 Martin Fowler 提出依赖注入概念
    Martin Fowler  Inversion of Control Containers and the Dependency Injection pattern  
    http://martinfowler.com/articles/injection.html


    DI

    2、什么是DI
    DI:依赖注入(Dependency Injection) :用一个单独的对象(装配器)来装配对象之间的依赖关系 。



    2、理解DI问题关键
    谁依赖于谁?           -------    应用程序依赖于IoC容器
    为什么需要依赖?        -------    应用程序依赖于IoC容器装配类之间的关系
    依赖什么东西?          -------    依赖了IoC容器的装配功能
    谁注入于谁?            -------    IoC容器注入应用程序
    注入什么东西?          -------    注入应用程序需要的资源(类之间的关系)
     
    更能描述容器其特点的名字 ——“依赖注入”(Dependency Injection)
    IoC容器应该具有依赖注入功能,因此也可以叫DI容器 

    3、DI优点
        【1】帮你看清组件之间的依赖关系,只需要观察依赖注入的机制(setter/构造器),就可以掌握整个依赖(类与类之间的关系)。
        【2】组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
        【3】依赖注入的目标并非为软件系统带来更多的功能,而是为了提升组件重用的概率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不用关心具体的资源来自何处、由谁实现。

    使用DI限制:组件和装配器(IoC容器)之间不会有依赖关系,因此组件无法从装配器那里获得更多服务,只能获得配置信息中所提供的那些。 

    4、实现方式
       1、构造器注入
       2、setter注入
       3、接口注入:在接口中定义需要注入的信息,并通过接口完成注入
           @Autowired
           public void prepare(MovieCatalog movieCatalog,
               CustomerPreferenceDao customerPreferenceDao) {
               this.movieCatalog = movieCatalog;
               this.customerPreferenceDao = customerPreferenceDao;
           }



    使用IoC/DI容器开发需要改变的思路
    1、应用程序不主动创建对象,但要描述创建它们的方式。
    2、在应用程序代码中不直接进行服务的装配,但要配置文件中描述哪一个组件需要哪一项服务。容器负责将这些装配在一起。

    其原理是基于OO设计原则的The Hollywood Principle:Don‘t call us, we’ll call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的(Passive),所有的组件初始化和装配都由容器负责。组件处在一个容器当中,由容器负责管理。

    IoC容器功能:实例化、初始化组件、装配组件依赖关系、负责组件生命周期管理。

    本质:
          IoC:控制权的转移,由应用程序转移到框架;
          IoC/DI容器:由应用程序主动实例化对象变被动等待对象(被动实例化);
          DI:  由专门的装配器装配组件之间的关系;
          IoC/DI容器:由应用程序主动装配对象的依赖变应用程序被动接受依赖

    关于IoC/DI与DIP之间的关系 详见 http://www.iteye.com/topic/1122310?page=5#2335746

     

    IoC/DI与迪米特法则 详见http://www.iteye.com/topic/1122310?page=5#2335748


    展开全文
  • Python装饰器的本质理解

    千次阅读 2013-07-24 00:30:53
    最近在华为做openstack相关的一些项目,顺便进修了一下Python知识,看到装饰器这一块时懵懂极了,网上找的大概都是例子,经过仔细研究揣摩,总结出了装饰器使用的本质规则,以备后查,希望Python装饰器有疑问的...

    我又回来了,深夜更文,神情仓促。。。最近在华为做openstack相关的一些项目,顺便进修了一下Python知识,看到装饰器这一块时懵懂极了,网上找的大概都是例子,经过仔细研究揣摩,总结出了装饰器使用的本质规则,以备后查,希望对Python装饰器有疑问的朋友有帮助。

    首先要理解Python具备的这几个特性:
    1、用类对象调用一个方法,方法的第一个实参self就是对象本身,如果方法不是通过类对象调用,则self实参是你显式传的参数,例如通过装饰器的方式传递,正是本文要 解释的

    这里的几处方法的调用都是通过对象的形式调用的,所以self形参就是调用者

     

     

    2、任何对象都可以当作方法,比如类本身是一个方法,对象也是一个方法,方法更是一个方法
       为什么类是方法:比如有一个类Cls,如果我们这样用Cls(),那么会默认调用构造函数__init__()
       为什么对象是方法:比如obj=Cls(),那么我们这样用obj(),则默认会调用Cls类里的__call__方法,当然__call__必须手动实现,美其名曰这个类实现了callable接口。
       为什么方法是方法这个就不用解释了,地球人都明白

     

    好了,接下来看看什么是装饰器吧,我们直接看跨类装饰
    1、首先让我们看看如何用一个类的方法装饰另一个类中的方法

    一、用Deco.dec来装饰myFunc,实际上是把myFunc作为参数传递给了Deco.dec方法,并返回另一个方法extendFunc
        使得以后调用myFunc的地方会转调用extendFunc
    二、由于装饰器语法的限制,用 Deco.dec装饰myFunc时必须用Deco类来引用(Deco.dec是通过类引用方法)
        因此注定了dec方法为类方法
    三、必须返回一个方法,这是装饰器的约定,否则在调用myFunc的时候就不知道调什么方法了
    四、调用了myFunc的地方就转而调用extendFunc,所以在执行extendFunc的时候第一个实参是mycls
    五、必须至少保留一个形参,因为你不知道调用者会传什么参数,所以我们这里可以使用可变参数*arg1和**arg2
    六、被装饰的方法变成了普通方法,而装饰的方法则替代了被装饰的方法

    七、被装饰的方法由于没有经过对象引用,直接传入装饰器,变成了普通方法,所以self形参变成了普通参数

     

    之前我们用方法类装饰方法,我们现在用类来装饰方法(其实也是用方法装饰方法,因为类也是方法,请记住刚才的特性之一)

     

     

     

    好了,最后进阶看一下下面这个案例

    展开全文
  • 初次看到信息熵的公式有很多不理解的地方,只知道信息熵如何进行计算,却不懂得公式背后的原理,我通过查阅了一些资料,加深了信息熵的理解,现在将这些理解分享给大家。如有疑问欢迎评论,若你有帮助,麻烦点个...

    一、序言

        初次看到信息熵的公式有很多不理解的地方,只知道信息熵如何进行计算,却不懂得公式背后的原理,我通过查阅了一些资料,加深了对信息熵的理解,现在将这些理解分享给大家。如有疑问欢迎评论,若对你有帮助,麻烦点个赞。未经允许、请勿转载。(本文适合只知道信息熵的公式,但是不明白其中原理的人进行阅读)

    二、什么是信息熵

        正如我们想要衡量某个物体的质量引入了克这个单位、我们想衡量时间,我们设计一秒钟这么长。香农老人家想要量化一条消息中带有的“信息量”的大小,提出了信息熵。
    那么,首先明确一个问题,什么样的消息算作“信息量大”呢?什么样的消息又算作“信息量小呢”?举个例子昨天小明和我说:“今天罗志祥又和周扬青秀恩爱了!”,我就觉得这有啥的,他们天天秀恩爱。也就是说小明的这条消息并不能给我带来很大的信息量。
    BUT今天小明和我说:”周扬青怒锤罗志祥!!!罗志祥人设崩塌!!!“,我就会很惊讶,因为这条消息给我的信息量很大。(类似的信息量很大的消息还有:小明告诉我今天太阳会从西边升起)
    我们用信息熵来描述一个事件混乱程度的大小(一个事件我们一定知道结果,那么这个事件的混乱程度就是0;一个时间充满随机性,我们猜不到或者很难猜到结果,那么他的混乱度就很大)
    引用下面一个在箱子里面摸球的例子,我们来更具体的了解信息熵。
    (此例引自:Youtube的一个视频
    在这里插入图片描述
    图左侧中有一个装有四个球的封闭箱子(这个箱子里面有三个红球、一个蓝球),现在我们从箱子中随机取出一个球,记录它的颜色后再放回箱子中,重复四次操作。如果你依次取出的序列为右上角所示(第一次取到红色、第二次取到红色、第三次取到红色、第四次取到蓝色),则你可以获得奖金;否则你就输了。大家用初中数学来算一算,我赢得奖金的概率是
    P ( x ) = 3 4 ∗ 3 4 ∗ 3 4 ∗ 1 4 = 27 256 P(x)=\frac{3}{4}*\frac{3}{4}*\frac{3}{4}*\frac{1}{4}=\frac{27}{256} Px=43434341=25627
      现在明确了这个游戏的规则,那么我们分析一下如下几个箱子与赢得奖金的情况,分别计算一下获胜概率
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    (每个图的左边是这个箱子的红球与蓝球初始条件,右侧是获胜所要求的序列,大家自己算算这个概率和图上写的一样吗?)
    在这里插入图片描述
    我们来分析一下这三种状态的游戏,第一次由于箱子内全是红球、该箱子的随机性很弱,也就是说还没摸我就知道结果了。这种状态带来的信息量很小;第三个箱子随机性很强,也就是说,对于结果我们充满未知。这个状态的信息量很大。我们算出的这个概率越接近1时候,这个信息熵应该越接近0;算出的这个概率越小的时候,信息熵反而应该越大。我们需要找到这么一个公式来满足这一点。(暂停思考一下,有哪些公式可以满足)
    该可以很轻松的想到,用刚才P(winning)的概率取倒数可以吗? 答案是,只考虑刚才的问题,是可以的。但取倒数这个方式还是存在一些问题,比如第三个箱子取0.0625的倒数,算出来的这个信息量为16,如果这个P(winning)概率算出结果很小时,取倒数后就会变得非常大,所以我们认为这个乘法的规则并不是很好(换言之,我们希望曲线平滑一些)。香农发现log函数可以很好的解决这个问题。 因为log(a*b) = log(a)+log(b);而恰巧像抽箱子的独立事件P(AB) = P(A)*P(B)。【原因不止于此,后面我们还会再详细讨论】。
    所以香农取了一个-log(x)这么一个函数来表示某一状态的信息量大小,因为x是概率事件取[0,1],所以log(x)是一个递增的恒负的值,取一个负号,-log(x)是一个恒正、递减的函数,正好符合我们的预期。
    在这里插入图片描述

    表的第四列就是我们用log计算出的结果。而我们刚刚是依次计算的每一个球的结果,为了表示系统的平均信息量。我们除4得到最终的信息熵。
    在这里插入图片描述
    我们来将这个模型一般化,m个红球n个蓝球,信息熵表示如上图所示。
    我们可以再将模型一般化一些,如果这个箱子里有多种不同颜色的球,我们就公式变成了如下的样子:
    H ( x ) = − ∑ i = 1 n P ( x i ) ∗ l o g ( P ( x i ) )   H_{(x)}= -\sum_{i=1}^{n}P_{(x_i)}*log(P(x_i))\, H(x)=i=1nP(xi)log(P(xi))
    这就是信息熵。也就是说,我们规定拿出一枚硬币,随意投出后,他可能是正面也可能是反面,它的信息熵是单位1(用刚才的方法来算算是不是1)。就像我们在这节开始所提到的,我们知道一个物体是几千克。是因为我们有一个1kg的砝码作为参考。我们能感受到时间流逝了多少秒,是因为我们规定了秒的单位。

    三、为什么是log

     这章我们会再用一个例子来讲解,为什么是信息熵为什么要用log?还是以一个游戏为例。在这里插入图片描述
    在上述的8个字母中,任取一个字母(我们不知道取的是什么,但我们知道初始的8个字母是什么),现在让你来猜这个字母是什么。
    利用我们刚刚学过的信息熵,我们可以知道第一个序列的信息熵很低、第三个最高。我们可以计算出如下结果
    在这里插入图片描述
    (这个信息熵大家自己算一下,和上面计算的方式完全一样)
    重点来了: 下面我们用一种提问的方式,来解决这个问题。你可以像系统提问(比如:这个字符是A吗?),系统会给你回答,你根据回答继续进行提问,直到猜到结果为止。以第二个序列为例;系统选了D,让你来猜。你会这样提问:
    Q1:这个字符是A吗? Answer:不是
    你就知道,这个答案只能是B,C,D中的一个,你就会继续提问:
    Q2:这个字符是B吗? Answer:不是
    你就会继续问:
    Q3:这个字符是C吗?Answer:不是
    好了,你不会再继续问下去了,因为这个答案一定是D。
    也就是说通过这种方式,如果答案是A,你会猜1次,答案是B你会猜两次,答案是C或者D,你会猜三次。平均猜测次数为
    E ( x ) = 1 4 ∗ 1 + 1 4 ∗ 2 + 1 4 ∗ 3 + 1 4 ∗ 3 = 2.25 次 E(x)=\frac{1}{4}*1+\frac{1}{4}*2+\frac{1}{4}*3+\frac{1}{4}*3=2.25次 Ex=411+412+413+413=2.25
    显然,你可以选择一种更精妙的提问方式,来缩减平均猜测的次数
    你可以这样进行提问:
    Q1:这个字符是A或B吗? Answer:不是
    Q2:那么这个字符是C吗? Answer:不是
    好了,那么我知道这个字符是D了。也就是通过这种方式,我们不管是哪一个字符,我们只需要问两次就可以解决问题,我们用一种更直观的树来表示,如下图所示
    在这里插入图片描述
    恰巧,这种提问二选一的过程,恰巧是个抛硬币的过程。由于我们类似的等价于抛了两次硬币,我们可以知道,这个过程的信息熵是2。我们再用信息熵的公式试一试
    H ( x ) = 1 4 ∗ l o g ( 4 ) + 1 4 ∗ l o g ( 4 ) + 1 4 ∗ l o g ( 4 ) + 1 4 ∗ l o g ( 4 ) = 2 H(x)=\frac{1}{4}*log(4)+\frac{1}{4}*log(4)+\frac{1}{4}*log(4)+\frac{1}{4}*log(4)=2 Hx=41log(4)+41log(4)+41log(4)+41log(4)=2
    (这里我们把符号直接化进log中了)

    大家发现没有,log(x)是不是恰巧等于x需要询问的次数呢?!!!这也是这个公式的精妙所在,在离散数学中我们学过,一个树的高度等于log(节点数),这个log(x)恰巧是询问的高度,也就是投硬币的次数!这原来就是使用log的原因
    上面的例子中A,B,C,D都是等概率出现的;下面我们将这个过程一般化,看一看当每个随机变量不等概率时的运算过程
    在这里插入图片描述

    我们看如上的序列,其中A出现的概率要等于BCD之和。所以我们为了让我们的提问次数最小化,我们要尽力讲每次提问的YorN分成等概率,也就是我们要问的第一个问题是:
    Q1:这个字符是A吗?
    如果不是,我们知道是B,C,D但是B的概率等于C和D之和,我们就再问:
    Q2:这个字符是B吗?
    如果不是,这时候C和D等概率,我们随便问一个即可:
    Q3:这个字符是C吗?
    好了,现在得出了结论。
    问出A需要1次,B2次,C和D都是三次。
    我们用信息熵来计算一下。
    H ( x ) = 1 2 ∗ l o g ( 2 ) + 1 4 ∗ l o g ( 4 ) + 1 8 ∗ l o g ( 8 ) + 1 8 ∗ l o g ( 8 ) H(x)=\frac{1}{2}*log(2)+\frac{1}{4}*log(4)+\frac{1}{8}*log(8)+\frac{1}{8}*log(8) Hx=21log(2)+41log(4)+81log(8)+81log(8)
    每一个log(x)恰巧对应着他所在的叶子在树的第几层,也就是他需要询问的次数,前面乘上一个概率,是不是发现这个公式提出的非常巧妙!!

    同时,在二进制计算机中,一个比特为0或1,其实就代表了一个二元问题的回答。也就是说,在计算机中,对于这个事件进行编码,所需要的平均码长为H(x)个比特。

    三、结语

     通过上述过程,相信大家能清楚的理解信息熵。本文并没有一些数学上详细的证明,暂时留个坑以后填。如果大家有什么问题,欢迎在评论区交流,如果觉得有用麻烦点个赞~
    参考资料:
    [1]https://www.youtube.com/watch?v=ErfnhcEV1O8
    [2]https://blog.csdn.net/v_JULY_v/article/details/40508465

    展开全文
  • 理解socket的本质

    千次阅读 2016-08-03 14:33:52
    一般来说,很多都会说, Socket 编程基本就是listen,accept以及send,write等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。 对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不...

    知其然更知其所以然,该文解答了困扰我很久的问题:What's socket indeed? 

           原文链接:socket通信原理 , 作者:zhshujun

           另外,要补充的是socket三种类型:Datagram socket(使用 UDP协议), stream socket(使用 TCP协议), Raw socket或Raw IP socket(路由器或其他网络设备使用)

    原文如下:

    要写网络程序就必须用Socket,这是程序员都知道的。而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,write等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。

    对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。对于TCP/IP,我们还知道TCP和UDP,前者可以保证数据的正确和可靠性,后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,很多时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。

    我们还知道如下几个事实:
    1。一个指定的端口号不能被多个程序共用。比如,如果IIS占用了80端口,那么Apache就不能也用80端口了。
    2。很多防火墙只允许特定目标端口的数据包通过。
    3。服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。

    于是,一个困惑了我很久的问题就产生了。如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?如果是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了--防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接请求和处理方式。我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?

    后来,我又仔细研读了TCP/IP的协议栈的原理,对很多概念有了更深刻的认识。比如,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to End)的数据包传送,这里的节点是一台网络设备,比如计算机。因为IP层只负责把数据送到节点,而不能区分上面的不同应用,所以TCP和UDP协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。

    所以,我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。

    TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!

    Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很相似,实际上在BSD系统里就是跟文件句柄一样存放在一样的进程句柄表里。这个socket其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等等。这些句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定的对象进行操作--这其实是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。

    现在我们知道,socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。

    现在我们明白,如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的连接建立过程。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。

    明白socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系,这很重要!



    1、TCP连接
    手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。

    建立起一个TCP连接需要经过“三次握手”:

    第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

    握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)


    2、HTTP连接

    HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。

    HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

    1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
    2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
    由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。


    3、SOCKET原理

    3.1套接字(socket)概念
    套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

    应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

     

    展开全文
  • 卷积的本质及物理意义(全面理解卷积)

    万次阅读 多人点赞 2017-02-18 20:14:19
    提示:卷积的理解分为三部分讲解1)信号的角度2)数学家的理解(外行)3)与多项式的关系 1 来源 卷积其实就是为冲击函数诞生的。“冲击函数”是狄拉克为了解决一些瞬间作用的物理现象而提出的符号。古人曰...
  • 合伙制度的一些理解

    千次阅读 2019-03-02 09:13:31
    合伙,就是一起做大事的。这些是如何做事的,我们简单分析下。 汉高祖刘邦,斩白色起义,一堆合伙,这些组到一起就是”事业合伙“,大家奔的是消灭...当然还有很多别的模式,但大同小异,本质不变。 ...
  • 彻底理解递归,从递归的本质说起!

    万次阅读 多人点赞 2018-05-12 14:28:35
    遍历二叉树,是学习树这种数据结构首先要理解的一种基本操作。比较简单地方式就是用递归去遍历,鉴于递归这种调用方法有一定的特殊性...递归调用的特殊性在于自己调用自己,给一种迷茫感,如果是递归调用“一次”...
  • *数学理解:上面的运算相当于输入空间进行了以下5中操作的转换,完成了从输入空间到输出空间的变换过程。 用线性变换跟随着非线性变化a,将输入空间投向另一个空间。 *从物质世界角度理解:   相当于...
  • 从OO的本质理解python中的self

    千次阅读 2013-12-22 20:33:11
    举个栗子,假设我要用户的数据进行操作,用户的数据包含name和age。如果用面向过程的话,实现出来是下面这样子的。 def user_init(user,name,age): user['name'] = name user['age'] = age def set_user_name...
  • 使用计算机二十多年了,总有一种执念,想看清计算机到底是什么,所以一直以来都在探索计算机的本质。到现在,自认为已经找到了,所以把它写下来,给后来者以参考。 计算机的本质到底是什么呢?穿越纷繁复杂的代码...
  • 理解矩阵和特征向量的本质

    万次阅读 多人点赞 2013-11-07 20:09:41
    理解矩阵和特征向量的本质 原文地址 最近复习矩阵论中,又是一堆定理和证明突然发现学了这么常时间的矩阵论、线性代数,记住的只是一堆莫名其妙的定理而已,一些本质的东西都没有搞清楚。 比如,为...
  • 大数据本质上是人类社会数据积累从量变到质变的必然产物,是在信息高速公路基础上的进一步升级和深化,提升人工系统智能水平的重要途径,人类社会的发展具有极其重大的影响和意义。 大数据是一个体量特别大、数据...
  • “安全的本质是信任问题”这句话是最早是在道哥的《白帽子讲WEB安全》一书中看到的。书中也拿机场、车站的安检做了举例,虽然在当时就感觉这话说的有道理,但并没产生共鸣。究其原因可能是当时所在公司的信息安全...
  • Android的理解

    万次阅读 多人点赞 2015-07-09 10:54:37
    前言写这篇文章是为了和大家描述下我Android的理解,同时会讲述下我后面的技术规划,希望能够大家有点参考价值。大家都想学好Android,那么怎么才能学好呢?这个真不好说,但是我可以和大家交流下我自己的心得,...
  • 大数据本质上是人类社会数据积累从量变到质变的必然产物,是在信息高速公路基础上的进一步升级和深化,提升人工系统智能水平的重要途径,人类社会的发展具有极其重大的影响和意义。 大数据是一个体量特别大、数据...
  • 99%的理解错了HTTP中GET与POST的区别

    万次阅读 多人点赞 2019-03-02 23:43:55
    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的都能说出一二。 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。 你可能自己写过无数个GET和POST请求,或者已经看...
  • 对理解卷积的数学物理意义很有帮助。 下面说一下我的理解: 1.卷积是求累积值,就是某一时刻的反应,是多个反应的叠加值。 2.既然如一,就有2.1任何信号可微分成脉冲信号的组合,依次通过系统。 2.1,...
  • 架构的本质

    千次阅读 2021-01-18 20:06:15
    1、架构的本质 物理学中有个很著名的“熵增定律”:一个封闭系统,都是从有序到无序,也就是它的熵 (即混乱程度)会不断地增加,最终系统会彻底变得无序。 这个理论放在软件系统的演化上,也是非常适用的。 一方面,...
  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,...就是C语言...
  • 形象理解线性代数的本质(三) 矩阵的升维和降维

    千次阅读 多人点赞 2019-06-09 02:52:57
    引子:降维打击 科幻小说《三体》里一种很...还用游戏的例子,有4个角色,每个都有不同的能力,将其用矩阵表示出来 现在我们要评估他们的两种能力:领兵打仗的能力和协同将领的能力 只要将两个矩阵相乘...
  • 通过自制CPU来彻底理解CPU的工作原理    每天摸着CPU,摸了20多年,却总是无法彻底理解CPU的工作原理,还有比这更郁闷的事吗?所以我决定攻克这一世界(我个人的世界)难题,自己做一个CPU来理解CPU的工作原理。...
  • 其实每个都能轻松而透彻地理解位图与矢量图的本质区别 位图与矢量图的区别(为什么要再进行解释)  播放录像时按空格键暂停/继续播放 (关于位图与矢量图的区别,各种教材和网上解释的有很多,但是本人认为解释...
  • 谈谈Spring IOC的理解

    万次阅读 多人点赞 2016-09-21 13:42:59
    学习过Spring框架的一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们Spring...
  • 洛克《人类理解论》

    千次阅读 2016-03-26 22:29:59
    首先是一段理性的定义,洛克认为理性是本质 通过观念、知识等概念的含义来描述本质特征,在十七章里具体的阐述了理性的含义。接下来是理性的五种具体形式:推理、三段论法、推论、意见和论证。最 后...
  • 聊聊C语言和指针的本质

    万次阅读 多人点赞 2019-11-24 21:07:34
    坐着绿皮车上海到杭州,24块钱,很宽敞,在火车上非正式地聊几句。 很多编程语言都以 “没有指针” 作为自己的优势来宣传,然而,对于C语言,指针却是与生俱来的。...为了理解本质,我们从计算机模型说起...
  • 我们都知道,人工智能是根据人类...通常来说,人工智能和人类智能的本质区别包括六部分,第一就是两者的进化途径和本质属性不一样,第二就是物质承担者不同,第三就是二者在智能活动中的地位不同,第四就是人工智能...
  • 工作多年,我架构的一些理解

    千次阅读 多人点赞 2020-07-13 09:41:54
    每一个程序员都听过架构这个词,每一个程序员都有自己对此的理解和看法,本文分享我架构的理解。 什么是架构? 因为我是程序员,所以本文讨论的架构特指软件架构(Soft Architecture)。 我看过很多关于架构方面的书...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 340,260
精华内容 136,104
关键字:

对人的本质的理解