史上最全!押题率90%的Android中高级工程师面试复习大纲及真题答案整理(上篇)Button123

转眼间2020就接近尾声了,年后有跳槽想法的小伙伴们心里应该也有自己的决定了。金三银四青铜五,总不能到跳槽的黄金期再开始复习吧。没办法,都是兄弟,宠着!2020年度Android中高级面试复习大全奉上。

废话就懒得多说了,进入正题。(再插一句:点赞都是好兄弟,白嫖都是好妹妹)

一文搞定Android中高级工程师面试必问所有知识点,希望可以通过此文帮助一些想换工作的朋友更好的复习,准备面试。

以下只整理列出面试频率较高的题

简单来说:HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存Entry对象。当两个对象的hashcode相同时,它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry会存储在链表中,当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。

有使用,它的底层是基于数组的数据结构,默认第一次初始化长度为10,由于add,put,size没有处理线程安全,所以它是非线程安全的。

要不我手动画一下它的整体结构吧。如下图所示。

图解:

有用过,它的底层数据结构是双向链表组成,我还是画一下它的结构图吧。如下所示:

JVM基本构成

从上图可知,JVM主要包括四个部分:

1.类加载器(ClassLoader):在JVM启动时或者在类运行将需要的class加载到JVM中。(下图表示了从java源文件到JVM的整个过程,可配合理解。

2.执行引擎:负责执行class文件中包含的字节码指令;

3.内存区(也叫运行时数据区):是在JVM运行的时候操作所分配的内存区。运行时内存区主要可以划分为5个区域,如图:

每当有线程被创建的时候,JVM就需要为其在内存中分配虚拟机栈和本地方法栈来记录调用方法的内容,分配程序计数器记录指令执行的位置,这样的内存消耗就是创建线程的内存代价。

Java内存模型即JavaMemoryModel,简称JMM。JMM定义了Java虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的。Java线程之间的通信总是隐式进行,并且采用的是共享内存模型。这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(mainmemory)中,每个线程都有一个私有的本地内存(localmemory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。总之,JMM就是一组规则,这组规则意在解决在并发编程可能出现的线程安全问题,并提供了内置解决方案(happen-before原则)及其外部可使用的同步手段(synchronized/volatile等),确保了程序执行在多线程环境中的应有的原子性,可视性及其有序性。

提到垃圾回收,我们可以先思考一下,如果我们去做垃圾回收需要解决哪些问题?

一般说来,我们要解决三个问题:

1、回收哪些内存?

2、什么时候回收?

3、如何回收?

这些问题分别对应着引用管理和回收策略等方案。

提到引用,我们都知道Java中有四种引用类型:

不同的引用类型,在做GC时会区别对待,我们平时生成的Java对象,默认都是强引用,也就是说只要强引用还在,GC就不会回收,那么如何判断强引用是否存在呢?

一个简单的思路就是:引用计数法,有对这个对象的引用就+1,不再引用就-1,但是这种方式看起来简单美好,但它却不能解决循环引用计数的问题。

因此可达性分析算法登上历史舞台,用它来判断对象的引用是否存在。

可达性分析算法通过一系列称为GCRoots的对象作为起始点,从这些节点从上向下搜索,所走过的路径称为引用链,当一个对象没有任何引用链与GCRoots连接时就说明此对象不可用,也就是对象不可达。

GCRoots对象通常包括:

可达性分析算法整个流程如下所示:

第二次标记:GC对F-Queue队列里的对象进行第二次标记,如果在第二次标记时该对象又成功被引用,则会被移除即将回收的集合,否则会被回收。

总之,JVM在做垃圾回收的时候,会检查堆中的所有对象否会被这些根集对象引用,不能够被引用的对象就会被圾收集器回收。一般回收算法也有如下几种:

1).标记-清除(Mark-sweep)

标记-清除算法采用从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收。标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。

2).标记-整理(Mark-Compact)

标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。该垃圾回收算法适用于对象存活率高的场景(老年代)。

3).复制(Copying)

复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于对象存活率低的场景,比如新生代。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。

4).分代收集算法

不同的对象的生命周期(存活情况)是不一样的,而不同生命周期的对象位于堆中不同的区域,因此对堆内存不同区域采用不同的策略进行回收可以提高JVM的执行效率。当代商用虚拟机使用的都是分代收集算法:新生代对象存活率低,就采用复制算法;老年代存活率高,就用标记清除算法或者标记整理算法。Java堆内存一般可以分为新生代、老年代和永久代三个模块:

1.所有新生成的对象首先都是放在新生代的。新生代的目标就是尽可能快速的收集掉那些生命周期短的对象。

2.新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。大部分对象在Eden区中生成。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空,如此往复。

3.当survivor1区不足以存放eden和survivor0的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次FullGC,也就是新生代、老年代都进行回收。

4.新生代发生的GC也叫做MinorGC,MinorGC发生频率比较高(不一定等Eden区满了才触发)。

1.在老年代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代中。因此,可以认为老年代中存放的都是一些生命周期较长的对象。

永久代主要存放静态文件,如Java类、方法等。永久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如使用反射、动态代理、CGLib等bytecode框架时,在这种时候需要设置一个比较大的永久代空间来存放这些运行过程中新增的类。

垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现:

Serial收集器(复制算法):新生代单线程收集器,标记和清理都是单线程,优点是简单高效;

SerialOld收集器(标记-整理算法):老年代单线程收集器,Serial收集器的老年代版本;

ParNew收集器(复制算法):新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;

ParallelOld收集器(标记-整理算法):老年代并行收集器,吞吐量优先,ParallelScavenge收集器的老年代版本;

G1(GarbageFirst)收集器(标记-整理算法):Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代。

JAVA自动内存管理:给对象分配内存以及回收分配给对象的内存。

1、对象优先在Eden分配,当Eden区没有足够空间进行分配时,虚拟机将发起一次MinorGC。

2、大对象直接进入老年代。如很长的字符串以及数组。很长的字符串以及数组。

3、长期存活的对象将进入老年代。当对象在新生代中经历过一定次数(默认为15)的MinorGC后,就会被晋升到老年代中。

4、动态对象年龄判定。为了更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

而程序在启动的时候,并不会一次性加载程序所要用到的class文件,而是根据程序的需要,通过Java的类加载制(ClassLoader)来动态加载某个class文件到内存当的,从而只有class文件被载入到了内存之后,才能被其它class文件所引用。所以ClassLoader就是用来动态加载class件到内存当中用的。

类的加载就是虚拟机通过一个类的全限定名来获取描述此类的二进制字节流,而完成这个加载动作的就是类加载器。

注:这里的相等性保函Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果以及Instance关键字对对象所属关系的判定结果等。

类加载器可以分为三类:

启动类加载器(BootstrapClassLoader):负责加载\lib目录下或者被-Xbootclasspath参数所指定的路径的,并且是被虚拟机所识别的库到内存中。

扩展类加载器(ExtensionClassLoader):负责加载\lib\ext目录下或者被java.ext.dirs系统变量所指定的路径的所有类库到内存中。

应用类加载器(ApplicationClassLoader):负责加载用户类路径上的指定类库,如果应用程序中没有实现自己的类加载器,一般就是这个类加载器去加载应用程序中的类库。

1、原理介绍

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(BootstrapClassLoader)本身没有父类加载器,但可以用作其它lassLoader实例的的父类加载器。

当一个ClassLoader实例需要加载某个类时,它会在试图搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器BootstrapClassLoader试图加载,如果没加载到,则把任务转交给ExtensionClassLoader试图加载,如果也没加载到,则转交给AppClassLoader进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等待URL中加载该类。

如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

类加载机制:

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法去内,然后在堆区创建一个java.lang.Class对象,用来封装在方法区内的数据结构。类的加载最终是在堆区内的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

类加载有三种方式:

1)命令行启动应用时候由JVM初始化加载

2)通过Class.forName()方法动态加载

3)通过ClassLoader.loadClass()方法动态加载

这么多类加载器,那么当类在加载的时候会使用哪个加载器呢?

这个时候就要提到类加载器的双亲委派模型,流程图如下所示:

双亲委派模型的整个工作流程非常的简单,如下所示:

如果一个类加载器收到了加载类的请求,它不会自己立去加载类,它会先去请求父类加载器,每个层次的类加器都是如此。层层传递,直到传递到最高层的类加载器只有当父类加载器反馈自己无法加载这个类,才会有当子类加载器去加载该类。

2、为什么要使用双亲委托这种模型呢?

因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要让子ClassLoader再加载一次。

考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(BootstrcpClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非你改变JDK中ClassLoader搜索类的默认算法。

3、但是JVM在搜索类的时候,又是如何判定两个class是相同的呢?

JVM在判定两个class是否相同时,不仅要判断两个类名否相同,而且要判断是否由同一个类加载器实例加载的。

只有两者同时满足的情况下,JVM才认为这两个class是相同的。就算两个class是同一份class字节码,如果被两个不同的ClassLoader实例所加载,JVM也会认为它们是两个不同class。

比如网络上的一个Java类org.classloader.simple.NetClassLoaderSimple,javac编译之后生成字节码文件NetClasLoaderSimple.class,ClassLoaderA和ClassLoaderB这个类加载器并读取了NetClassLoaderSimple.class文件并分别定义出了java.lang.Class实例来表示这个类,对JVM来说,它们是两个不同的实例对象,但它们确实是一份字节码文件,如果试图将这个Class实例生成具体的对象进行转换时,就会抛运行时异常java.lang.ClassCastException,提示这是两个不同的类型。

答:Java中的反射首先是能够获取到Java中要反射类的字节码,获取字节码有三种方法:

1.Class.forName(className)

2.类名.class

3.this.getClass()。

然后将字节码中的方法,变量,构造函数等映射成相应的Method、Filed、Constructor等类,这些类提供了丰富的方法可以被我们所使用。

Java有四种线程池:

第一种:newCachedThreadPool

不固定线程数量,且支持最大为Integer.MAX_VALUE的线程数量:

1、线程数无限制。2、有空闲线程则复用空闲线程,若无空闲线程则新建线程。3、一定程序减少频繁创建/销毁线程,减少系统开销。

第二种:newFixedThreadPool

一个固定线程数量的线程池:

publicstaticExecutorServicenewFixedThreadPool(intnThreads,ThreadFactorythreadFactory){//corePoolSize跟maximumPoolSize值一样,同时传入一个无界阻塞队列//该线程池的线程会维持在指定线程数,不会进行回收returnnewThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue(),threadFactory);}定长线程池:

1、可控制线程最大并发数(同时执行的线程数)。2、超出的线程会在队列中等待。

第三种:newSingleThreadExecutor

可以理解为线程数量为1的FixedThreadPool:

publicstaticExecutorServicenewSingleThreadExecutor(){//线程池中只有一个线程进行任务执行,其他的都放入阻塞队列//外面包装的FinalizableDelegatedExecutorService类实现了finalize方法,在JVM垃圾回收的时候会关闭线程池returnnewFinalizableDelegatedExecutorService(newThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue()));}单线程化的线程池:

1、有且仅有一个工作线程执行任务。2、所有任务按照指定顺序执行,即遵循队列的入队出队规则。

第四种:newScheduledThreadPool。

支持定时以指定周期循环执行任务:

publicstaticScheduledExecutorServicenewScheduledThreadPool(intcorePoolSize){returnnewScheduledThreadPoolExecutor(corePoolSize);}注意:前三种线程池是ThreadPoolExecutor不同配置的实例,最后一种是ScheduledThreadPoolExecutor的实例。

从数据结构的角度来看,线程池主要使用了阻塞队列(BlockingQueue)和HashSet集合构成。从任务提交的流程角度来看,对于使用线程池的外部来说,线程池的机制是这样的:

1、如果正在运行的线程数=coreSize,把该task放入阻塞队列;3、如果队列已满&&正在运行的线程数=maximumPoolSize,线程池调用handler的reject方法拒绝本次提交。理解记忆:1-2-3-4对应(核心线程->阻塞队列->非核心线程->handler拒绝提交)。

线程池的线程复用:

这里就需要深入到源码addWorker():它是创建新线程的关键,也是线程复用的关键入口。最终会执行到runWoker,它取任务有两个方式:

信号量

semaphore可用于进程间同步也可用于同一个进程间的线程同步。

可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

1、ArrayBlockingQueue

是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。

2、LinkedBlockingQueue

一个基于链表结构的阻塞队列,此队列按FIFO(先进先出)排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()和Executors.newSingleThreadExecutor使用了这个队列。

3、SynchronousQueue

一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。

4、PriorityBlockingQueue

一个具有优先级的无限阻塞队列。

1.初始的poolSize

与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于corePoolSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加,若后续仍有新的任务加入,而没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略。

Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue.

对于BlockingQueue,想要实现阻塞功能,需要调用put(e)take()方法。而ConcurrentLinkedQueue是基于链接节点的、无界的、线程安全的非阻塞队列。

HTTPS是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。

HTPPS和HTTP的概念:

超文本传输协议(HTTP-Hypertexttransferprotocol)是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

如下图所示,可以很明显的看出两个的区别:

注:TLS是SSL的升级替代版,具体发展历史可以参考传输层安全性协议。

HTTP与HTTPS在写法上的区别也是前缀的不同,客户端处理的方式也不同,具体说来:

如果URL的协议是HTTP,则客户端会打开一条到服务端端口80(默认)的连接,并向其发送老的HTTP请求。如果URL的协议是HTTPS,则客户端会打开一条到服务端端口443(默认)的连接,然后与服务器握手,以二进制格式与服务器交换一些SSL的安全参数,附上加密的HTTP请求。所以你可以看到,HTTPS比HTTP多了一层与SSL的连接,这也就是客户端与服务端SSL握手的过程,整个过程主要完成以下工作:

交换协议版本号选择一个两端都了解的密码对两端的身份进行认证生成临时的会话密钥,以便加密信道。SSL握手是一个相对比较复杂的过程,更多关于SSL握手的过程细节可以参考TLS/SSL握手过程

SSL/TSL的常见开源实现是OpenSSL,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。更多源于OpenSSL的技术细节可以参考OpenSSL。

HTTP的缓存机制也是依赖于请求和响应header里的参数类实现的,最终响应式从缓存中去,还是从服务端重新拉取,HTTP的缓存机制的流程如下所示:

HTTP的缓存可以分为两种:

上面提到强制缓存使用的的两个标识:

private:客户端可以缓存。public:客户端和代理服务器都可缓存。max-age=xxx:缓存的内容将在xxx秒后失效no-cache:需要使用对比缓存来验证缓存数据。no-store:所有内容都不会缓存,强制缓存,对比缓存都不会触发。我们再来看看对比缓存的两个标识:

Last-Modified/If-Modified-Since

Etag/If-None-MatchETag是资源文件的一种标识码,当客户端发送第一次请求时,服务端会返回当前资源的标识码:

ETag:"5694c7ef-24dc"客户端再次发送,会在header里携带上次服务端返回的资源标识码:

If-None-Match:"5694c7ef-24dc"服务端接收到客户端发来的资源标识码,则会与自己当前的资源吗进行比较,如果不同,则说明资源已经被修改,则返回200,如果相同则说明资源没有被修改,返回304,客户端可以继续使用缓存。

加密算法的类型基本上分为了两种:

此外,还有Hash加密算法

HASH算法:MD5,SHA1,SHA256

HTTPS=HTTP+SSL,HTTPS的加密就是在SSL中完成的。

这就要从CA证书讲起了。CA证书其实就是数字证书,是由CA机构颁发的。至于CA机构的权威性,那么是毋庸置疑的,所有人都是信任它的。CA证书内一般会包含以下内容:

假设现在有客户端A和服务器B:

简化如下:

可以发现,在HTTPS加密原理的过程中把对称加密和非对称加密都利用了起来。即利用了非对称加密安全性高的特点,又利用了对称加密速度快,效率高的好处。

当数据传输发生在一个设备(PC/手机)和网络服务器之间时,攻击者使用其技能和工具将自己置于两个端点之间并截获数据;尽管交谈的两方认为他们是在与对方交谈,但是实际上他们是在与干坏事的人交流,这便是中间人攻击。

在这种技术中,攻击者会将恶意数据包注入常规数据中。这样用户便不会注意到文件/恶意软件,因为它们是合法通讯流的一部分。

在SSL剥离攻击中,攻击者使SSL/TLS连接剥落,随之协议便从安全的HTTPS变成了不安全的HTTP。

ACK:TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1

SYN(SYNchronization):在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1.因此,SYN置1就表示这是一个连接请求或连接接受报文。

FIN(finis)即完,终结的意思,用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。

第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,SequenceNumber为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置AcknowledgmentNumber为x+1(SequenceNumber+1);同时,自己还要发送SYN请求信息,将SYN位置为1,SequenceNumber为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK报文段。然后将AcknowledgmentNumber设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

第一次分手:主机1(可以使客户端,也可以是服务器端),设置SequenceNumber和AcknowledgmentNumber,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;

第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,AcknowledgmentNumber为SequenceNumber加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。主要目的防止server端一直等待,浪费资源。换句话说,即是为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。

“四次挥手”原因是因为tcp是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。

数据校验。

数据合理分片与排序,TCP会对数据进行分片,接收方会缓存为按序到达的数据,重新排序后再提交给应用层。

流程控制:当接收方来不及接收发送的数据时,则会提示发送方降低发送的速度,防止包丢失。

拥塞控制:当网络发生拥塞时,减少数据的发送。

1、基于连接与无连接;

2、对系统资源的要求(TCP较多,UDP少);

3、UDP程序结构较简单;

4、流模式与数据报模式;

5、TCP保证数据正确性,UDP可能丢包;

6、TCP保证数据顺序,UDP不保证。

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式。如不考虑拥塞处理,可靠UDP的简单设计如下:

目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT:

1、RUDP(ReliableUserDatagramProtocol)

RUDP提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等。

2、RTP(RealTimeProtocol)

RTP为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。

3、UDT(UDP-basedDataTransferProtocol)

UDT的主要目的是支持高速广域网上的海量数据传输。

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

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

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。

很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。TCP(TransmissionControlProtocol)传输控制协议

正常连接断开客户端会给服务端发送一个fin包,服务端收到fin包后才会知道连接断开。而断网断电时客户端无法发送fin包给服务端,所以服务端没办法检测到客户端已经短线。为了缓解这个问题,服务端需要有个心跳逻辑,就是服务端检测到某个客户端多久没发送任何数据过来就认为客户端已经断开,这需要客户端定时向服务端发送心跳数据维持连接。

2、应用层心跳机制实现。

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候Session信息都是放在内存的。

当客户端访问服务器时,服务器根据需求设置Session,将会话信息保存在服务器上,同时将标示Session的SessionId传递给客户端浏览器,

以后浏览器每次请求都会额外加上这个参数值,服务器会根据这个SessionId,就能取得客户端的数据信息。

THE END
1.制度不规范。不要去,不要去,不要去。我在这家公司工作过,虽然只是...职Q(zq.zhaopin.com)是智联招聘旗下专业的招聘求职社交问答平台,覆盖了求职、招聘、职业规划、升职加薪、面试技巧、工作经验分享等热门话 题,涉及各种行业职场问题,2.6亿用户的职场社区https://zq-mobile.zhaopin.com/zpdShareMomentDetail/19906178/
2.BOSS直聘黑猫投诉本人在boss直聘上找外卖类工作,线上跟招聘软件上是说车辆由他们提供不收取任何费用,在线下面试中,对方先是让我充三百激活电话卡,说会退钱再诱骗我签约合同使用拍小租租车,在我把车还给他之后还不跟我取消合同,拒绝退款 [投诉对象]BOSS直聘客服 [投诉要求]退款,赔偿 ...https://fj.tousu.sina.com.cn/company/view/?couid=5400760171
3.烟台中宠食品有限公司怎么样?面试经验工资待遇2019-06-30 17:57:11 查看全部面试我要分享 烟台中宠食品有限公司新增一条来自 前员工/在职员工 分享的工资待遇,包括以下内容: “基本工资年终奖是否有保险是否有公积金是否准时下班周六周天是否加班” 详情>> 2019-04-13 10:59:07 我要分享 烟台中宠食品有限公司.新增一条来自 前员工/在职员工 分享的工资待遇...https://m.job592.com/pay/com1922147.html
4.$中宠股份(SZ002891)$太强势了作者: $中宠股份(SZ002891)$太强势了https://xueqiu.com/5796100774/312522432
5.女子面试中被公司宠物狗咬伤?公司:她主动逗狗今日头条前段时间 长沙的韩女士通过网络平台 为自己的婆婆向女士 找到了一份清洁工的工作 工作内容也包括喂养公司的宠物狗 可没曾想还没入职 婆婆在面试参观该公司的过程中 就被狗咬伤了 当事人的儿媳 韩女士: 8月12号来面试 保安带我们上去参观 说楼上喂了狗 ...https://m.gmw.cn/toutiao/2022-08/31/content_1303118573.htm
6.逃妻太娇:梁少怀中宠手机阅读现代言情逃妻太娇:梁少怀中宠 “梁少爷,你是怎么和沈小姐在一起的?”“日久生情!”梁晨宇冷声道。“听说,昨夜沈小姐又爬墙出去了……”梁晨宇阴沉着脸转身就走,沈歌遥。 冬南西北瓜现代言情118.7万字 暖婚甜宠 “顾安生,你轻点,我疼……”“乖,你叫声老公,我就轻点。”看着正在帮自己按摩足底的某某总裁,安宁一阵无...http://m.idejian.cn/book/12955495
7.中宠股份(002891)股票价格行情提供中宠股份(002891)股票的行情走势、五档盘口、逐笔交易等实时行情数据,及中宠股份(002891)的新闻资讯、公司公告、研究报告、行业研报、F10资料、行业资讯、资金流分析、阶段涨幅、所属板块、财务指标、机构观点、行业排名、估值水平、股吧互动等与中宠股份(002891)有关http://quote.eastmoney.com/concept/SZ002891.html?from=data
8.第三季度净利大增七成,“中宠股份们”的宠物生意有多好做?“公司以宠物食品的研发、生产和销售为主要业务,产品覆盖犬用及猫用宠物食品主粮、湿粮、零食、保健品等品类。公司以‘宠物既是人类的朋友,更是我们的家人’为企业理念……”中宠股份在财报中这样介绍自己。 10月22日,中宠股份涨停收盘,股价上涨10.02%,收盘价为29.76元。业绩层面,中宠股份2024年前三季度实现营业收...https://www.xinhuanet.com/fashion/20241023/7fa26a32b9914c219893c9b5a2388a8f/c.html
1.网络招聘陷阱4个类型网申技巧网络招聘陷阱花样繁多,求职者需要提高警惕,掌握必要的网申技巧,才能在求职过程中规避风险,顺利找到理想的工作。选择正规招聘平台、核实公司信息、谨慎对待收费要求、保护个人信息、注意面试细节、签订正规劳动合同,是求职者自我保护的重要手段。希望本文的介绍能为广大求职者提供有益的参考,帮助大家顺利实现职业梦想。 https://www.aixzzs.com/list/19370.html
2.帐中宠:腹黑王爷太高冷(居橘)最新章节吧2.读者在帐中宠:腹黑王爷太高冷全文阅读中如发现内容有与法律抵触之处,请马上向本站举报。希望您多多支持本站,非常感谢您的支持! 3.本小说《帐中宠:腹黑王爷太高冷》是本好看的言情小说,但其内容仅代表作者居橘本人的观点,与快书库阅读网的立场无关。 4.如果如果读者在阅读帐中宠:腹黑王爷太高冷时对作品内容...https://www.kuaishuku.com/52832/
3.帐中宠:腹黑王爷太高冷居橘曲歌小说提供(居橘)大神最新小说《帐中宠:腹黑王爷太高冷》最新章节全文免费阅读,帐中宠:腹黑王爷太高冷txt下载,帐中宠:腹黑王爷太高冷5200,帐中宠:腹黑王爷太高冷无弹窗!请关注帐中宠:腹黑王爷太高冷吧,本站最新最快更新帐中宠:腹黑王爷太高冷最新章节。https://www.bequgexs.com/77/77586/
4.喵星人汪星人也IPO路演这家撒狗粮的中宠股份太有爱不错,这正是中宠股份(002891,诊股)IPO网上路演。你或许不知道中宠股份,但如果你问一问周边养宠物的朋友知不知道"Wanpy"这个宠物零食品牌,估计大多数人都会报以会心的微笑。他们肯定还会问一句"啊?这家企业要上市啦?代码是多少?"如果认可彼得·林奇的"跟着老婆孩子逛商超"是寻找大牛股最有效方法的话,那么,下面...https://item.btime.com/039006te2n9utj3t5tlcupm6m40?from=haossk2
5.宠物美容师证面试题及答案.宠物美容师证面试题及答案解析3、请问您如何处理宠物在洗浴过程中可能出现的抗拒行为? 答:我会与宠物建立信任关系,让它们感受到我的善意,我会用温柔的语言和动作安抚宠物,让它放松下来,我会根据宠物的性格和需求,采用不同的方法进行洗浴,对于胆小的宠物,我会先从头部开始洗浴,逐步过渡到全身;对于活泼好动的宠物,我会选择一个安全的环境进行洗浴...https://wp.xueertui.cn/361775.html
6.《掌中宠他总想和我BE》画饼成真晋江文学城94 第94 章[VIP] 慕言坐在窗边拿着把剪刀一点儿一点儿地修剪瓶中的花枝,瓶子里插的 7109 2024-07-29 23:58:00 *最新更新 非v章节章均点击数:2003 总书评数:524 当前被收藏数:1987 营养液数:1386 文章积分:28,660,468 到最新章 №1 作者评论 评论: 《掌中宠他总想和我BE》 打分:0 发表时间...https://www.795.jjwxc.net/onebook.php?novelid=4696918
7.保研面试/考研复试英语口语常见问题整理从研究经验来看,我发现自己在很多方面都在改进。首先,通过阅读大量前沿学术文献,对机器学习有了更深入的了解。其次,我在框架设计和数据分析方面学到了更多的技能。此外,我的交流能力也在这次研究中得到了提高。 12. 请介绍一本你最近看过/最喜欢的专业书籍 ...https://blog.csdn.net/weixin_43595277/article/details/120519303
8.2018下半年教师资格证面试120道结构化试题及解析(1月5日)(二...2018下半年教师资格证面试考试于本周末(2019年1月5日-6日)进行,山香教育根据学员回忆及时整理了2018下半年各学段各学科教师资格证面试试题汇总,欢迎大家收藏本页,我们将实时进行更新。 61.谈谈你对四有教师的理解 四有:做好老师要有理想信念,有道德情操,有扎实学识有仁爱之心。 https://www.zhaojiao.net/jiaoshi/show-5127.html
9.第098章一生无虞掌中宠 糖莫莫 2197字 2021-07-10 21:07:26 到底是遐想呵,麳 眼前这人,显然不是如此。 他不知道她究竟因何想要置他于死地, 是因着对顾家的恨,对昔日夺位之仇? 还是,在为着昨夜之事,怪罪他? 他不知道。 但记忆犹新的是, 在昨夜那场荒诞至极的情事中,麳 她娇喘着的, 心心念念的, 从始至终都是...https://www.hongxiu.com/chapter/19318117101147204/55124013328348322
10.「中宠股份工资待遇怎么样」烟台中宠食品股份有限公司薪酬福利加班...中宠股份招聘要求怎么样:中宠股份都在招什么人? 中宠股份招聘类别客户服务类最多占13%,其次是工厂生产类占13%。中宠股份什么学历能进?本科最多占90%,其次是大专占5%。工作经验中宠股份有什么要求?1-3年最多占40%,其次是不限经验占35%。中宠股份工作地区在哪?烟台最多占85%,其次是上海占15%。 https://www.jobui.com/company/12309328/salary/