络筒机报文错误 33440是报文格式错误什么意思思

a是否带静电手套和静电环 正在翻译,请等待...

a你的哥哥现在在学校吗?

a我听说你们国家的男人可以娶好几个老婆 Я услышал вашей стране человек может пожениться несколько супруг

他们的衣领是否是蓝色,白色或者桃红色

aあなたを待つ私を愛し 等待您的我它是亲爱的

a尤其是语文 正在翻译,请等待...

a小河静悄悄 正在翻译,请等待...

a我刚刚买了一本英语书 正在翻译,请等待...


a是否带静电手套和静电环 正在翻译,请等待...

a你的哥哥现在在学校吗?

a我听说你们国家的男人可以娶好几个老婆 Я услышал вашей стране человек может пожениться несколько супруг

他们的衣领是否是蓝色,白色或者桃红色

aあなたを待つ私を愛し 等待您的我它是亲爱的

a尤其是语文 正在翻译,请等待...

a小河静悄悄 正在翻译,请等待...

a我刚刚买了一本英语书 正在翻译,请等待...


Java研发工程师知识点总结



  •  一、Java基础(语言、集合框架、OOP、设计模式等)
  •  三、多线程和并发
  •  六、算法与数据结构
  •  七、计算机网络

 一、Java基础(语言、集合框架、OOP、设计模式等)

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。

StrongReference:Java 的默认引用实现, 它会尽可能长时间的存活于 JVM 内,当没有任何对象指向它时将会被GC回收

SoftReference:尽可能长时间保留引用,直到JVM内存不足,适合某些缓存应用

WeakReference:顾名思义, 是一个弱引用, 当所引用的对象在 JVM 内不再有强引用时, 下一次将被GC回收

PhantomReference:它是最弱的一种引用关系,也无法通过PhantomReference取得对象的实例。仅用来当该对象被回收时收到一个通知

WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。

当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从 32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU 缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM 主要动机在于可以指定最大堆大小,通过压缩 OOP 可以节省一定的内存。通过 -XX:+UseCompressedOops 选项,JVM

理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5 GB,Solaris 大约 3GB。64 位 JVM允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

Time compilation),当代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。

当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个后台进程,回收无效对象的内存用于将来的分配。

25. 怎么获取 Java 程序使用的内存?堆使用的百分比?

可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory() 方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。

26. Java 中堆和栈有什么区别?

JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

可查看堆空间大小分配(年轻代、年老代、持久代分配) 提供即时的垃圾回收功能 垃圾监控(长时间监控回收情况)

查看堆内类、对象信息查看:数量、类型等

有了堆信息查看方面的功能,我们一般可以顺利解决以下问题:

年老代年轻代大小划分是否合理 内存泄漏 垃圾回收算法设置是否合理

线程信息监控:系统线程数量。 线程状态监控:各个线程都处在什么样的状态下

Dump线程详细信息:查看线程内部运行情况 死锁检查

CPU热点:检查系统哪些方法占用的大量CPU时间 内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)

系统两个不同运行时刻,对象(或类、线程等)的不同

举例说,我要检查系统进行垃圾回收以后,是否还有该收回的对象被遗漏下来的了。那么,我可以在进行垃圾回收前后,分别进行一次堆情况的快照,然后对比两次快照的对象情况。

内存泄露的定义: 当某些对象不再被应用程序所使用,但是由于仍然被引用而导致垃圾收集器不能释放。

内存泄漏的原因:对象的生命周期不同。比如说对象A引用了对象B. A的生命周期比B的要长得多,当对象B在应用程序中不会再被使用以后, 对象 A 仍然持有着B的引用. (根据虚拟机规范)在这种情况下GC不能将B从内存中释放。这种情况很可能会引起内存问题,倘若A还持有着其他对象的引用,那么这些被引用的(无用)对象也不会被回收,并占用着内存空间。甚至有可能B也持有一大堆其他对象的引用。这些对象由于被B所引用,也不会被垃圾收集器所回收,所有这些无用的对象将消耗大量宝贵的内存空间。并可能导致内存泄漏。

1、当心集合类, 比如HashMap, ArrayList等,因为这是最容易发生内存泄露的地方.当集合对象被声明为static时,他们的生命周期一般和整个应用程序一样长。

b.清理程序中的重复的Jar文件,减少类的重复加载

发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap Space的size有关。解决这类问题有两种思路:

  1. 检查程序,看是否存在死循环或不必要地重复创建大量对象,定位原因,修改程序和算法。

  2. 通过虚拟机参数-Xms和-Xmx设置初始堆和最大堆的大小

直接内存并不是Java虚拟机规范定义的内存区域的一部分,但是这部分内存也被频繁使用,而且也可能导致OOM异常的出现。

JDK1.4引入了NIO,这是一种基于通道和缓冲区的非阻塞IO模式,它可以使用Native函数库分配直接堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,使得在某些场合显著提高性能,因为它避免了在Java堆和本地堆之间来回复制数据。

每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时 volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。

32. 双亲委派模型中的方法

一般来说 I/O 模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞 四种IO模型

同步阻塞 IO : 在此种方式下,用户进程在发起一个 IO 操作以后,必须等待 IO 操作的完成,只有当真正完成了 IO 操作以后,用户进程才能运行。 JAVA传统的 IO 模型属于此种方式!

同步非阻塞 IO: 在此种方式下,用户进程发起一个 IO 操作以后可返回做其它事情,但是用户进程需要时不时的询问 IO 操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的 CPU 资源浪费。其中目前 JAVA 的 NIO 就属于同步非阻塞 IO 。

异步阻塞 IO : 此种方式下是指应用发起一个 IO 操作以后,不等待内核 IO 操作的完成,等内核完成 IO 操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问 IO 是否完成,那么为什么说是阻塞的呢?因为此时是通过 select 系统调用来完成的,而 select 函数本身的实现方式是阻塞的,而采用 select 函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性!

异步非阻塞 IO: 在此种模式下,用户进程只需要发起一个 IO 操作然后立即返回,等 IO 操作真正的完成以后,应用程序会得到 IO 操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的 IO 读写操作,因为 真正的 IO读取或者写入操作已经由 内核完成了。目前 Java7的AIO正是此种类型。

BIO即同步阻塞IO,适用于连接数目较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的唯一选择,但程序直观、简单、易理解。

NIO即同步非阻塞IO,适用于连接数目多且连接比较短的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

AIO即异步非阻塞IO,适用于连接数目多且连接比较长的架构,如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK1.7开始支持

34. 类加载器按照层次,从顶层到底层,分别加载哪些类?

启动类加载器:负责将存放在JAVA_HOME/lib下的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。

扩展类加载器:这个加载器负责加载JAVA_HOME/lib/ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器

应用程序类加载器:这个加载器是ClassLoader中getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(Classpath)上所指定的类库,可直接使用这个加载器,如果应用程序没有自定义自己的类加载器,一般情况下这个就是程序中默认的类加载器

只需要继承ClassLoader,并覆盖findClass方法。 在调用loadClass方法时,会先根据委派模型在父加载器中加载,如果加载失败,则会调用自己的findClass方法来完成加载


  • Statement是最基本的用法, 不传参, 采用字符串拼接,存在注入漏洞

由上可以看出,PreparedStatement有预编译的过程,已经绑定sql,之后无论执行多少遍,都不会再去进行编译,而 statement 不同,如果执行多遍,则相应的就要编译多少遍sql,所以从这点看,preStatement 的效率会比 Statement要高一些

  • 代码的可读性和可维护性

有很多的最佳实践,你可以根据你的喜好来例举。下面是一些更通用的原则:

a)使用批量的操作来插入和更新数据

d)通过列名来获取结果集,不要使用列的下标来获取

4. 数据库索引的实现

数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:

1、根结点至少有两个子女; 2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1; 3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ; 4、所有的叶子结点都位于同一层。

由于B-Tree的特性,在B-Tree中按key检索数据的算法非常直观:首先从根节点进行二分查找,如果找到则返回对应节点的data,否则对相应区间的指针指向的节点递归进行查找,直到找到节点或找到null指针,前者查找成功,后者查找失败。

一个度为d的B-Tree,设其索引N个key,则其树高h的上限为logd((N+1)/2),检索一个key,其查找节点个数的渐进复杂度为O(logdN)。从这点可以看出,B-Tree是一个非常有效率的索引数据结构。

B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构。

B+树是B树的变形,它把所有的data都放在叶子结点中,只将关键字和子女指针保存于内结点,内结点完全是索引的功能。

1、每个节点的指针上限为2d而不是2d+1。

2、内节点不存储data,只存储key;叶子节点存储data不存储指针。

一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针。

在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针

例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

为什么B树(B+树)?

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。

这涉及到磁盘存取原理、局部性原理和磁盘预读。

先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:

每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(h)=O(logdN)。一般实际应用中,出度d是非常大的数字,通常超过100,因此h非常小(通常不超过3)。

综上所述,用B-Tree作为索引结构效率是非常高的。

而红黑树这种结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。

至于B+Tree为什么更适合外存索引,原因和内节点出度d有关。

由于B+Tree内节点去掉了data域,因此可以拥有更大的出度,拥有更好的性能。


1. 二叉搜索树:(Binary Search Tree又名:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。

二叉搜索树:(Binary Search Tree又名:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。

红黑树是一棵二叉搜索树,它在每个结点上增加一个存储位来表示结点的颜色,可以是RED或BLACK。通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树没有一条路径会比其他路径长出2倍,所以红黑树是近似平衡的,使得红黑树的查找、插入、删除等操作的时间复杂度最坏为O(log n),但需要注意到在红黑树上执行插入或删除后将不在满足红黑树性质,恢复红黑树的属性需要少量(O(log n))的颜色变更(实际是非常快速的)和不超过三次树旋转(对于插入操作是两次)。虽然插入和删除很复杂,但操作时间仍可以保持为 O(log n) 次。具体如何保证?引出红黑树的5个性质。

红黑树的5个性质:满足以下五个性质的二叉搜索树

  1. 每个结点或是红色的或是黑色的
  2. 如果一个结点是红色的,则它的两个子结点是黑色的
  3. 对于每个结点,从该结点到其后代叶结点的简单路径上,均包含相同数目的黑色结点

由于性质的约束,插入的结点都是红色的。插入时性质1、3始终保持。破坏性质2当且仅当当前插入结点为根节点。变一下颜色即可。如果是破坏性质4或5,则需要旋转和变色来继续满足红黑树的性质。下面说一说插入的几种情况,约定当前插入结点为N,其父结点为P,叔叔为U,祖父为G

情形1:树空,直接插入违反性质1,将红色改黑。

情形2:N的父结点为黑,不必修改,直接插入

从情形3开始的情形假定N结点的父结点P为红色,所以存在G,并且G为黑色。且N存在一个叔叔结点U,尽管U可能为叶结点。

情形3:P为红,U为红(G结点一定存在且为黑)这里不论P是G的左孩子还是右孩子;不论N是P的左孩子还是右孩子。

首先把P、U改黑,G改红,并以G作为一个新插入的红结点重新进行各种情况的检查,若一路检索至根节点还未结束,则将根结点变黑。

情形4:P为红,U为黑或不存在(G结点一定存在且为黑),且P为G的左孩子,N为P的左孩子(或者P为G的右孩子,N为P的右孩子,保证同向的)。 P、G右旋并将P、G变相反色。因为P取代之前黑G的位置,所以P变黑可以理解,而G变红是为了不违反性质5。

情形5:P为红,U为黑或不存在,且P为G的左孩子,N为P的右孩子(或P为G的右孩子,N为P的左孩子,保证是反向的),对N,P进行一次左旋转换为情形4

删除操作比插入复杂一些,但最多不超过三次旋转可以让红黑树恢复平衡。

  • 黑高从某个结点x出发(不含x)到达一个叶结点的任意一条简单路径上的黑色结点个数称为该结点的黑高。红黑树的黑高为其根结点的黑高。
  • 一个具有n个内部结点的红黑树的高度h<=2lg(n+1)
  • 动态集合操作最坏时间复杂度为O(lgn)
  • 稳定排序:插入排序、冒泡排序、归并排序、基数排序

  • 插入排序[稳定] 适用于小数组,数组已排好序或接近于排好序速度将会非常快 复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

  • 树排序[不稳定] 应用:TreeSet的add方法、TreeMap的put方法 不支持相同元素,没有稳定性问题 复杂度:平均最差O(nlogn)

九大内部排序算法代码及性能分析参见我的

简单、均匀,不易产生冲突。但需事先知道关键字的分布情况,适合查找表较小且连续的情况,故现实中并不常用

平方取中法 折叠法 更多....

闭散列(开放地址方法):要求装填因子a较小,闭散列方法把所有记录直接存储在散列表中

  • 线性探测:易产生堆积现象(基地址不同堆积在一起)

开散列(链地址法):原地处理

  • 同义词记录存储在一个单链表中,散列表中子存储单链表的头指针。
  • 优点:无堆积 事先无需确定表长 删除结点易于实现 装载因子a>=1,缺点:需要额外空间

目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等。 想象一下,给你一张草稿纸,一只笔,一个编辑器,你能立即实现一颗红黑树,或者AVL树 出来吗? 很难吧,这需要时间,要考虑很多细节,要参考一堆算法与数据结构之类的树, 还要参考网上的代码,相当麻烦。 用跳表吧,跳表是一种随机化的数据结构,目前开源软件 Redis 和 LevelDB 都有用到它, 它的效率和红黑树以及 AVL 树不相上下,但跳表的原理相当简单,只要你能熟练操作链表, 就能去实现一个 SkipList。

跳跃表是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间),并且对并发算法友好。

Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,是一种“空间来换取时间”的一个算法,在每个节点中增加了指向下一层的指针,在插入、删除、查找时可以忽略一些不可能涉及到的结点,从而提高了效率。

在Java的API中已经有了实现:分别是

(1) 由很多层结构组成,level是通过一定的概率随机产生的

(2) 每一层都是一个有序的链表,默认是升序

(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现

(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素

在某一节点的左孩子的左子树上插入一个新的节点,使得该节点不再平衡。 举例 A B Ar Bl Br 在Bl下插入N,执行一次右旋即可,即把B变为父结点,原来的根节点A变为B的左孩子,B的右子树变为A的左子树。

与LL型是对称的,执行一次左旋即可。

指在AVL树某一结点左孩子的右子树上插入一个结点,使得该节点不在平衡。这时需要两次旋转,先左旋再右旋。

与LR对称,执行一次右旋,再执行一次左旋。

1、被删的节点是叶子节点

将该节点直接从树中删除,并利用递归的特点和高度的变化,反向推算其父节点和祖先节点是否失衡。

2、被删的节点只有左子树或只有右子树

将左子树(右子树)替代原有节点的位置,并利用递归的特点和高度的变化,反向推算父节点和祖先节点是否失衡。

3、被删的节点既有左子树又有右子树

找到被删节点的左子树的最右端的节点,将该结点的的值赋给待删除结点,再用该结点的左孩子替换它本来的位置,然后释放该结点,并利用递归特点,反向推断父节点和祖父节点是否失衡。

第一:简单介绍 一致性哈希算法是分布式系统中常用的算法。比如,一个分布式的存储系统,要将对象存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,N是机器节点数。

1、考虑到比如一个服务器down掉,服务器结点N变为N-1,映射公式必须变为key%(N-1)

2、访问量加重,需要添加服务器结点,N变为N+1,映射公式变为hash(object)%(N+1)

当出现1,2的情况意味着我们的映射都将无效,对服务器来说将是一场灾难,尤其是对缓存服务器来说,因为缓存服务器映射的失效,洪水般的访问都将冲向后台服务器。

第二点:hash算法的单调性

Hash 算法的一个衡量指标是单调性,单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。

consistent hash 也是一种hash 算法,简单的说,在移除 / 添加一个结点时,它能够尽可能小的改变已存在的映射关系,尽可能的满足单调性的要求。

第三点:将对象和服务器结点分别映射到环型空间

通常的一致性哈希做法是将 value 映射到一个 32 位的 key 值,也即是 0~2^32-1 次方的数值空间;我们可以将这个空间想象成一个首( 0 )尾( 2^32-1 )相接的圆环。

我们可以通过hash函数将我们的key映射到环型空间中,同时根据相同的哈希算法把服务器也映射到环型空间中,顺便提一下服务器或者某个计算节点的 hash 计算,一般的方法可以使用机器的 IP 地址或者机器名作为 hash 输入。

第四点:将对象映射到服务器

在这个环形空间中,如果沿着顺时针方向从对象的 key 值出发,直到遇见一个 服务器结点,那么就将该对象存储在这个服务器结点上,因为对象和服务器的hash 值是固定的,因此这个 cache 必然是唯一和确定的。

这时候考察某个服务器down机或者需要添加服务器结点,也就是移除和添加的操作,我们只需要几个对象的映射。

Hash 算法的另一个指标是平衡性 (Balance)。平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。

对于上述的做法,可能导致某些对象都映射到某个服务器,使得分布不平衡。为此可以采用“虚拟结点”的做法。

“虚拟结点”( virtual node )是实际节点在 hash 空间的复制品,一实际结点对应了若干个“虚拟节点”,这个对应个数也成为“复制个数”,“虚拟节点”在 hash 空间中以 hash 值排列。引入“虚拟结点”会让我们的映射分布更为平衡一些。

8. 如何判断链表是否有环

方法1:快慢指针法 2.设两个工作指针p、q,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。比如p从A走到D,用了4步,而q则用了14步。因而步数不等,出现矛盾,存在环。

  • [排序算法] 快速排序

停止等待协议是最基本的数据链路层协议,它的工作原理是这样的。

在发送端,每发送完一帧就停止发送,等待接收端的确认,如果收到确认就发送下一帧。

在接收端,每收到一个无差错的帧,就把这个帧交付上层并向发送端发送确认。若该帧有差错,就丢弃,其他什么也不做。

停止等待协议为了可靠交付,需要对帧进行编号,由于每次只发送一帧,所以停止等待协议使用1个比特编号,编号0和1

停止等待协议会出现死锁现象(A等待B的确认),解决办法,启动超时计时器,超时计时器有一个重传时间。重传时间一般选择略大于“正常情况下从发完数据帧到收到确认帧所需的平均时间”。

再说滑动窗口之前,先说下连续ARQ,连续ARQ又称Go-back-N ARQ,意思是当出现差错必须重传时,要向回走N个帧,然后再开始重传,也就意味着只要有一帧出现差错,即使已经正确的帧也需要重传,白白浪费时间,增大开销。为此,应该对发送出去但未被确认的帧的数目加以限制,这就是滑动窗口协议。滑动窗口指收发两端分别维护一个发送窗口和接收窗口,发送窗口有一个窗口值Wt,窗口值Wt代表在没有收到对方确认的情况下最多可以发送的帧的数目。当发送的帧的序号被接收窗口正确收下后,接收端向前滑动并向发送端发去确认,发送端收到确认后,发送窗口向前滑动。收发两端按规律向前推进。

连续ARQ和选择重传ARQ均是窗口大于1的滑动窗口协议,而停止等待协议相当于收发两端窗口等于1。

滑动窗口指接收和发送两端的窗口按规律不断向前推进,是一种流量控制的策略。

1.HTTP/1.0协议使用非持久连接,即在非持久连接下,一个tcp连接只传输一个Web对象。 2.HTTP/1.1默认使用持久连接(然而,HTTP/1.1协议的客户机和服务器可以配置成使用非持久连接)。在持久连接下,不必为每个Web对象的传送建立一个新的连接,一个连接中可以传输多个对象。

1.安全性上说:get的方式是把数据在地址栏中明文的形式发送,URL中可见,POST方式对用户是透明的,安全性更高。 2.数据量说:Get传送的数据量较小,一般不能大于2KB,POST传送的数据量更大。 3.适用范围说:查询用Get,数据添加、修改和删除建议Post

5.TCP/IP体系各层功能及协议

主要负责将数据发送到网络传输介质上以及从网络上接收TCP/IP数据报,相当于OSI参考模型的物理层和数据链路层。在实际中,先后流行的以太网、令牌环网、ATM、帧中继等都可视为其底层协议。它将发送的信息组装成帧并通过物理层向选定网络发送,或者从网络上接收物理帧,将去除控制信息后的IP数据报交给网络层。

网际层主要功能是寻址和对数据报的封装以及路由选择功能。这些功能大部分通过IP协议完成,并通过地址解析协议ARP、逆地址解析协议RARP、因特网控制报文协议ICMP、因特网组管理协议IGMP从旁协助。所以IP协议是网络层的核心。

网际协议IP:IP协议是一个无连接的协议,主要负责将数据报从源结点转发到目的结点。也就是说IP协议通过对数据报中源地址和目的地址进行分析,然后进行路由选择,最后再转发到目的地。需要注意的是:IP协议只负责对数据进行转发,并不对数据进行检查,也就是说,它不负责数据的可靠性,这样设计的主要目的是提高IP协议传送和转发数据的效率。

ARP:该协议负责将IP地址解析转换为计算机的物理地址。

虽然我们使用IP地址进行通信,但IP地址只是主机在抽象的网络层中的地址。最终要传到数据链路层封装成MAC帧才能发送到实际的网络。因此不管使用什么协议最终需要的还是硬件地址。

每个主机拥有一个ARP高速缓存(存放所在局域网内主机和路由器的IP地址到硬件地址的映射表)

(1)A在自己的ARP高速缓存中查到B的MAC地址,写入MAC帧发往此B

(2)没查到,A向本局域网广播ARP请求分组,内容包括自己的地址映射和B的IP地址

(3)B发送ARP响应分组,内容为自己的IP地址到物理地址的映射,同时将A的映射写入自己的ARP高速缓存(单播的方式)

注:ARP Cache映射项目具有一个生存时间。

RARP:将计算机物理地址转换为IP地址

ICMP:该协议主要负责发送和传递包含控制信息的数据报,这些控制信息包括了哪台计算机出现了什么错误,网络路由出现了什么错误等内容。

传输层主要负责应用进程间“端到端”的通信,即从某个应用进程传输到另一个应用进程,它与OSI参考模型的传输层功能类似。

传输层在某个时刻可能要同时为多个不同的应用进程服务,因此传输层在每个分组中必须增加用于识别应用进程的标识,即端口。

TCP/IP体系的传输层主要包含两个主要协议,即传输控制协议TCP和用户数据报协议UDP。TCP协议是一种可靠的、面向连接的协议,保证收发两端有可靠的字节流传输,进行了流量控制,协调双方的发送和接收速度,达到正确传输的目的。

UDP是一种不可靠的、无连接的协议,其特点是协议简单、额外开销小、效率较高,不能保证可靠传输。

传输层提供应用进程间的逻辑通信。它使应用进程看见的就好像是在两个运输层实体间一条端到端的逻辑通信信道。

当运输层采用TCP时,尽管下面的网络是不可靠的,但这种逻辑通信信道相当于一条全双工的可靠信道。可以做到报文的无差错、按序、无丢失、无重复。

注:单单面向连接只是可靠的必要条件,不充分。还需要其他措施,如确认重传,按序接收,无丢失无重复。

1.发送之前无需建立连接,减小了开销和发送数据的时延

2.UDP不使用连接,不使用可靠交付,因此主机不需要维护复杂的参数表、连接状态表

3.UDP用户数据报只有8个字节的首部开销,而TCP要20字节。

4.由于没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(IP电话等实时应用要求源主机以恒定的速率发送数据是有利的)

UDP的过程(以TFTP举例):

1.服务器进程运行着,等待TFTP客户进程的服务请求。客户端TFTP进程启动时,向操作系统申请一个临时端口号,然后操作系统为该进程创建2个队列, 入队列和出队列。只要进程在执行,2个队列一直存在。

2.客户进程将报文发送到出队列中。UDP按报文在队列的先后顺序发送。在传送到IP层之前给报文加上UDP首部,其中目的端口后为69,然后发给IP层。 出队列若溢出,则操作系统通知应用层TFTP客户进程暂停发送。

3.客户端收到来自IP层的报文时,UDP检查报文中目的端口号是否正确,若正确,放入入队列队尾,客户进程按先后顺序一一取走。若不正确,UDP丢弃该报文,并请ICMP发送”端口不可达“差错报文给服务器端。入队列可能会溢出,若溢出,UDP丢弃该报文,不通知对方。

UDP首部:源端口 - 目的端口 - 长度 - 检验和,每个字段22字节。

注:IP数据报检验和只检验IP数据报的首部,而UDP的检验和将首部和数据部分一起都检验。

TCP报文段是面向字节的数据流。

TCP首部:20字节固定首部

确认比特ACK,ACK=1 确认号字段才有效;同步比特SYN:SYN=1 ACK=0表示一个连接请求报文段;终止比特FIN,FIN=1时要求释放连接。

窗口:将TCP收发两端记为A和B,A根据TCP缓存空间的大小确定自己的接收窗口大小。并在A发送给B的窗口字段写入该值。作为B的发送窗口的上限。意味着B在未收到A的确认情况下,最多发送的字节数。

选项:最大报文段长度MSS,MSS告诉对方TCP:我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节。若主机未填写,默认为536字节。

TCP的可靠是使用了序号和确认。当TCP发送一个报文时,在自己的重传队列中存放一个副本。若收到确认,删除副本。

TCP报文段的发送时机:1.维持一个变量等于MSS,发送缓存达到MSS就发送 2.发送端应用进程指明要发送,即TCP支持的PUSH操作。3.设定计时器

TCP的拥塞控制:TCP使用慢开始和拥塞避免算法进行拥塞控制

接收端根据自身资源情况控制发送端发送窗口的大小。

每个TCP连接需要维持一下2个状态变量:

接收端窗口rwnd(receiver window):接收端根据目前接收缓存大小设置的窗口值,是来自接收端的流量控制

拥塞窗口cwnd(congestion window):是发送端根据自己估计的网络拥塞程度设置的窗口值,是来自发送端的流量控制

慢开始算法原理:主机刚开始发送数据时,如果立即将较大的发送窗口的全部字节注入网络,由于不清楚网络状况,可能会引起拥塞。通常的做法是将cwnd设置为1个MSS,每收到一个确认,将cwnd+1,由小到大逐步增大cwnd,使分组注入网络的速率更加合理。为了防止拥塞窗口增长引起网络拥塞,还需设置一个状态变量ssthresh,即慢开始门限。

拥塞避免算法使发送端的拥塞窗口每经过一个RTT增加一个MSS(而不管在此期间收到多少ACK),这样,拥塞窗口cwnd按线性规律增长,拥塞窗口此时比慢开始增长速率缓慢很多。这一过程称为加法增大,目的在于使拥塞窗口缓慢增长,防止网络过早拥塞。

无论是慢开始还是拥塞避免,只要发送端发现网络出现拥塞(根据是没有按时收到ACK或者收到重复ACK),就将慢开始门限ssthresh设置为拥塞窗口值的一半并将拥塞窗口cwnd置为1,重新执行慢开始算法。这一过程称为乘法减小。目的在于迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

上述TCP确认都是通过捎带确认执行的。

上述的慢开始和拥塞避免算法是早期TCP使用的拥塞控制算法。因为有时TCP连接会在重传时因等待重传计时器的超时时间而空闲。为此在快重传中规定:只要发送端一连收到三个重复的ACK,即可断定分组丢失,不必等待重传计数器,立即重传丢失的报文。

与快重传搭配使用的还有快恢复:当不使用快恢复时,发送端若发现网络拥塞就将拥塞窗口降为1,然后执行慢开始算法,这样的缺点是网络不能很快恢复到正常状态。快恢复是指当发送端收到3个重复的ACK时,执行乘法减小,ssthresh变为拥塞窗口值的一半。但是cwnd不是置为1,而是ssthresh+3xMSS。若收到的重复ACK 为n(n > 3),则cwnd=ssthresh+n*MSS.这样做的理由是基于发送端已经收到3个重复的ACK,它表明已经有3个分组离开了网络,它们不在消耗网络的资源。

注意的是:在使用快恢复算法时,慢开始算法只在TCP连接建立时使用。

每发送一个报文段,就对这个报文段设置一次计时器。新的重传时间=γ*旧的重传时间。

TCP连接建立和释放的过程

SYN置1和FIN的报文段要消耗一个序号。

应用层位于TCP/IP体系结构的最高一层,也是直接为应用进程服务的一层,即当不同的应用进程数据交换时,就去调用应用层的不同协议实体,让这些实体去调用传输层的TCP或者UDP来进行网络传输。具体的应用层协议有,SMTP 25、DNS 53、HTTP 80、FTP 20数据端口 21控制端口、TFTP 69、TELNET 23、SNMP 161等

按网络拓扑结构:总线、星型、环型、树型、网状结构和混合型。

按覆盖范围:局域网、城域网、广域网

按传播方式:广播网络和点对点网络

广播式网络是指网络中的计算机使用一个共享信道进行数据传播,网络中的所有结点都能收到某一结点发出的数据信息。

单播:一对一的发送形式。

组播:采用一对一组的发送形式,将数据发送给网络中的某一组主机。

广播:采用一对所有,将数据发送给网络所有目的结点。

点对点网络中两个结点间的通信方式是点对点的。如果两台计算机之间没有直连的线路,则需要中间结点的接收、存储、转发直至目的结点。

6. TCP的三次握手和四次挥手的过程

连接建立(三次握手):首先Client端发送连接请求报文SYN并进入SYN_SENT状态,Server收到后发送ACK+SYN报文,并为这次连接分配资源。Client端接收到Server端的SYN+ACK后发送三次握手的最后一个ACK,并分配资源,连接建立。

7. 为什么连接建立是三次握手,而连接释放要四次挥手?

因为当Server端收到Client端发送的SYN连接请求报文后,可以直接发送SYN+ACK报文,其中ACK用来应答,SYN用来同步。但是关闭连接时,当Server端收到FIN报文后,并不会立即关闭socket,所以先回复一个ACK,告诉Client端“你的FIN我收到了”,只有等Server端的所有报文发送完了,Server端才发送FIN报文,因此不能一起发送,故需要四次挥手。

8. 为什么TIME_WAIT状态需要2MSL(最大报文段生存时间)才能返回Closed状态?

这是因为虽然双方都同意关闭连接了,而且四次挥手的报文也都协调发送完毕。但是我们必须假想网络是不可靠的,无法保证最后发送的ACK报文一定被对方收到,因此处于LAST_ACK状态下的 Server端可能会因未收到ACK而重发FIN,所以TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

请求行由三部分组成,分别是请求方法,请求地址,Http版本

报文主体:只在POST方法请求中存在。

状态行:第一部分为Http版本,第二部分为响应状态码 第三部分为状态码的描述

100 continue 初始请求已接受,客户端应继续发送请求剩余部分

返回内容:即Http请求的信息,可以是HTML也可以是图片等等。

Https即Secure Hypertext Transfer Protocol,即安全超文本传输协议,它是一个安全通信信道,基于Http开发,用于在客户机和服务器间交换信息。它使用安全套接字层SSL进行信息交换,是Http的安全版。

Https协议需要到CA申请证书,一般免费证书很少,需要交费。

Http是超文本传输协议,信息是明文传输,https则是具有安全性的tls/ssl加密传输协议。

11. 浏览器输入一个URL的过程

  1. 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址

  2. 解析出IP地址后,根据IP地址和默认端口80和服务器建立TCP连接

  3. 浏览器发出Http请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器

  4. 服务器做出响应,把对应的请求资源发送给浏览器

中间人获取server发给client的公钥,自己伪造一对公私钥,然后伪造自己让client以为它是server,然后将伪造的公钥发给client,并拦截client发给server的密文,用伪造的私钥即可得到client发出去的内容,最后用真实的公钥对内容加密发给server。

解决办法:数字证书,证书链,可信任的中间人

误码率:传输错误的比特与传输总比特数的比率

计算冗余码(余数R)的方法:先补0(n个)再对生成多项式取模。

CRC只能表示以接近1的概率认为它没有差错。但不能做到可靠传输。可靠传输还需要确认和重传机制。

14. 数据链路层的协议

15. 截断二进制指数退避算法

是以太网用于解决当发生碰撞时就停止发送然后重发再碰撞这一问题。

截断二进制指数退避算法:基本退避时间为2τ k=min{重传次数,10} r=random(0~2^k-1) 重传所需时延为r倍的基本退避时间


八、操作系统(OS基础、Linux等)

“并行”是指无论从微观还是宏观,二者都是一起执行的,也就是同一时刻执行 而“并发”在微观上不是同时执行的。是在同一时间间隔交替轮流执行

2. 进程间通信的方式

  • 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

  • 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

  • 信号量( semophore ) :信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

  • 消息队列( message queue ) 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

  • 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。

  • 套接字( socket ) :套接字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

1、阻塞IO模型 以socket为例,在进程空间调用recvfrom,其系统调用知道数据包到达且被复制到应用进程的缓冲区或者发生错误才返回,在此期间一直等待,进程从调用recvfrom开始到它返回的整段时间内都是被阻塞的,因此称为阻塞IO

2、非阻塞IO模型 应用进程调用recvfrom,如果缓冲区没有数据直接返回EWOULDBLOCK错误。一般对非阻塞IO进行轮询,以确定是否有数据到来。

开启套接字接口信号驱动IO功能,并通过系统调用sigaction执行信号处理函数。当数据准备就绪时,为该进程生成SIGIO信号,通过信号回调通知应用程序调用recvfrom来读取数据,并通知主函数处理数据。

告知内核启动某个操作,并让内核在整个操作完成后通知我们。它与信号驱动IO的区别在于信号驱动IO由内核通知我们何时可以开始IO操作。而异步IO模型由内核通知我们IO操作已经完成。

1. 开源软件有哪些?

Apache:相对宽松与MIT类似的协议,考虑有专利的情况。适用:Apache服务器、SVN

GPL:GPLV2和GPLV3,如果你在乎作品的传播和别人的修改,希望别人也以相同的协议分享出来。

LGPL:主要用于一些代码库。衍生代码可以以此协议发布(言下之意你可以用其他协议),但与此协议相关的代码必需遵循此协议。

上面各协议只是针对软件或代码作品,如果你的作品不是代码,比如视频,音乐,图片,文章等,共享于公众之前,也最好声明一下协议以保证自己的权益不被侵犯,CC协议。

我要回帖

更多关于 报文格式错误什么意思 的文章

 

随机推荐