android

1.什么是面向對象?

其本質是以建立模型體現(xiàn)出來的抽象思維過程和面向對象的方法,是一種編程思維,也是一種思考問題的方式。面向對象的三大特性:封裝,繼承,多態(tài)。

2.基本數(shù)據(jù)類型

byte: 屬于Java中的整型,長度為1字節(jié)8bit,取值10000000(-128)到 01111111(127),變量初始化默認值為0,包裝類Byte;
short: 屬于Java中的整型,長度為2字節(jié)16bit,取值10000000 00000000(-32768)到 01111111 11111111(32767),變量初始化默認值為0,包裝類Short;
int: 屬于Java中的整型,長度為4字節(jié)32bit,取值-2^31 (-2,147,483,648)到 2^31-1(2,147,483,647),變量初始化默認值為0,包裝類Integer;
long: 屬于Java中的整型,長度為8字節(jié)64bit,取值-2^63 (-9,223,372,036,854,775,808)到 2^63-1(9,223,372,036,854,775,8087),變量初始化默認值為0或0L,包裝類Long;
float: 屬于Java中的浮點型,也叫單精度浮點型,長度為4字節(jié)32bit,變量初始化默認值0.0f,包裝類Float;小數(shù)類型默認的double類型;
double: 屬于Java中的浮點型,也叫雙精度浮點型,長度為8字節(jié)64bit,變量初始化默認值0.0d,包裝類Double;float 和 double 都是表示浮點型的數(shù)據(jù)類型,它們之間的區(qū)別在于精確度的不同。
boolean: 屬于java中的布爾型,占1bit,1/8字節(jié),僅有兩個值true, false,變量初始化默認值false,包裝類Boolean;
char:屬于java中的字符型,占2字節(jié)16bit,可以賦值單字符以及整型數(shù)值, 變量初始化無默認值,包裝類Character;

String、StringBuilder與StringBuffer

String是內容不可變的,而StringBuffer、StringBuilder都是內容可變的。StringBuffer是同步的,數(shù)據(jù)安全的,但是效率低; StringBuilder是不同步的,數(shù)據(jù)不安全,相比于來說,效率高。

3.final finally finalize

final類不能被繼承,因此final類的成員方法沒有機會被覆蓋,默認都是final的。在設計類時候,如果這個類不需要子類,類的實現(xiàn)細節(jié)不運行改變,并且確定這個類不會被擴展,那么可以把這個類設計為final類。
finally關鍵字一般在異常中使用,配合try catch 一起使用,表示不管是否發(fā)生異常,finally中的內容一定會被執(zhí)行。
finalize方法名,Object類的方法,java技術運行使用finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是在垃圾收集器在確定這個對象沒有引用指向它時調用。finalize()方法是在垃圾收集器刪除對象之前對這個對象調用的子類覆蓋finalize()方法以整理系統(tǒng)資源或執(zhí)行其他清理操作。

4.==與equals區(qū)別

“==”常用來比較基本數(shù)據(jù)類型,8種基本數(shù)據(jù)類型有byte、short、long、double、char、int、float、boolean,因為變量直接存儲的就是他們的值,所以用"=="去比較,比較的就是他們的值。
但是復合數(shù)據(jù)類型用“==”比較的是他的堆內存地址。
“equals”對于復合數(shù)據(jù)類型比較的也是它的堆內存地址(不能作用于基本數(shù)據(jù)類型的變量)。

5.內部類、靜態(tài)內部類、匿名內部類、局部內部類

內部類:內部類是一個編譯的概念,一旦編譯成功,就會成為完全不同的兩個類,分別為outer.class和outer$inner.class類。內部類的成員變量/方法名可以和外部類的相同??梢院芎玫膶崿F(xiàn)隱藏,可實現(xiàn)多重繼承,可以避免修改接口而實現(xiàn)同一個類中兩種同名方法的調用。
靜態(tài)內部類:靜態(tài)內部類與非靜態(tài)內部類的區(qū)別在于:靜態(tài)內部類沒有x 指向外部的引用。在靜態(tài)內部類new一個外部類的對象,可以訪問外部的非公開的(private 修飾的)成員變量與方法(jdk1.8測試),靜態(tài)內部類中可以定義靜態(tài)或者非靜態(tài)的成員。在外部類中,創(chuàng)建的靜態(tài)內部類對象可以直接訪問對象中的所有成員變量和方法,無論是否是私有的。
匿名內部類:為了免去給內部類命名,或者只想使用一次,就可以選擇使用匿名內部類。
于匿名內部類沒有自己的名字,所以其在實例化時,必須繼承一個父類(可以是一個抽象類)或者實現(xiàn)一個接口,但是也只能是二者選其一,而不能即繼承父類,又實現(xiàn)接口。而且其繼承和實現(xiàn)都是隱式的,不是顯式的使用extends和implement關鍵字來繼承和實現(xiàn)的。由于匿名內部類不能是抽象類,所以它必須要實現(xiàn)它的抽象父類或者接口里面所有的抽象方法。匿名內部類不能定義任何靜態(tài)成員、方法。局部內部類的所有限制同樣對匿名內部類生效。匿名內部類訪問的外部類成員變量或成員方法必須用final修飾;jdk1.8可以不需要顯式的聲明
局部內部類:指內部類定義在方法體內,在局部內部類前不加修飾符public或private。局部內部類不能被public、private、static修飾;局部內部類中不可定義靜態(tài)變量或方法,當訪問外部方法的局部變量(即方法內的變量)時,變量必須是final修飾的的(jdk1.8環(huán)境下可以不顯式的加final,但是我們不能對變量進行修改操作,因為它是默認final型的)。

6.java反射

反射是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都 能夠調用它的任意一個方法和屬性;優(yōu)點:可以動態(tài)執(zhí)行,在運行期間根據(jù)業(yè)務功能動態(tài)執(zhí)行方法、訪問屬性,最大限度發(fā)揮了java的靈活性。缺點:對性能有影響,這類操作總是慢于直接執(zhí)行java代碼。

8.數(shù)據(jù)結構

常見的數(shù)據(jù)結構有:線性鏈表,數(shù)組,棧,隊列,樹和二叉樹
線性鏈表:采用動態(tài)分配內存的形式實現(xiàn),用一組任意的存儲單元存放數(shù)據(jù)元素鏈表的,一般為每個元素增設指針域,用來指向后繼元素。
數(shù)組必須事先定義固定的長度(元素個數(shù)),不能適應數(shù)據(jù)動態(tài)地增減的情況。當數(shù)據(jù)增加時,可能超出原先定義的元素個數(shù);當數(shù)據(jù)減少時,造成內存浪費;數(shù)組可以根據(jù)下標直接存取。
棧:先進后出的數(shù)據(jù)結構。
隊列:先進先出 FIFO(first in first out),新元素(等待進入隊列的元素)總是被插入到鏈表的尾部,而讀取的時候總是從鏈表的頭部開始讀取。
樹: 是一種數(shù)據(jù)結構,它是由n(n>=1)個有限結點組成一個具有層次關系的集合。
二叉樹:是每個結點最多有兩個子樹的樹結構。

9.HashMap

Hashmap是有數(shù)組+鏈表+紅黑樹組成的數(shù)據(jù)結構。HashMap采用Entry數(shù)組來存儲key-value對,每一個鍵值對組成了一個Entry實體,Entry類實際上是一個單向的鏈表結構,它具有Next指針,可以連接下一個Entry實體。 只是在JDK1.8中,鏈表長度大于8的時候,鏈表會轉成紅黑樹。數(shù)組是用來確定桶的位置,利用元素的key的hash值對數(shù)組長度取模得到. 鏈表是用來解決hash沖突問題,當出現(xiàn)hash值一樣的情形,就在數(shù)組上的對應位置形成一條鏈表。在hashmap插入數(shù)據(jù)的時候通過計算key的hash值,如果hash值沒有碰撞就直接放到數(shù)組對應的鏈表中。如果hash值碰撞了,就以鏈表形式存放。如果碰撞導致鏈表過長,就會把鏈表轉換成紅黑樹。從hashmap獲取數(shù)據(jù),根據(jù)key計算出hash值,如果鏈表中第一個節(jié)點就命中直接返回。如果有沖突,通過key.equals去查找對應的元素。Hashmap默認長度16,在插入數(shù)據(jù)的時候,通過load factor因子判斷是否需要擴容,默認0.75。

10.Hashmap與hashtable的區(qū)別:

兩者最主要的區(qū)別在于Hashtable是線程安全,而HashMap則非線程安全。
Hashtable的實現(xiàn)方法里面都添加了synchronized關鍵字來確保線程同步,因此相對而言HashMap性能會高一些,我們平時使用時若無特殊需求建議使用HashMap,在多線程環(huán)境下若使用HashMap需要使用Collections.synchronizedMap()方法來獲取一個線程安全的集合(Collections.synchronizedMap()實現(xiàn)原理是Collections定義了一個SynchronizedMap的內部類,這個類實現(xiàn)了Map接口,在調用方法時使用synchronized來保證線程同步,當然了實際上操作的還是我們傳入的HashMap實例,簡單的說就是Collections.synchronizedMap()方法幫我們在操作HashMap時自動添加了synchronized來實現(xiàn)線程同步,類似的其它Collections.synchronizedXX方法也是類似原理)。
HashMap可以使用null作為key,而Hashtable則不允許null作為key。
雖說HashMap支持null值作為key,不過建議還是盡量避免這樣使用,因為一旦不小心使用了,若因此引發(fā)一些問題,排查起來很是費事。
HashMap以null作為key時,總是存儲在table數(shù)組的第一個節(jié)點上。
HashMap是對Map接口的實現(xiàn),HashTable實現(xiàn)了Map接口和Dictionary抽象類。
HashMap的初始容量為16,Hashtable初始容量為11,兩者的填充因子默認都是0.75。
HashMap擴容時是當前容量翻倍即:capacity2,Hashtable擴容時是容量翻倍+1。即:capacity2+1
兩者計算hash的方法不同,Hashtable計算hash是直接使用key的hashcode對table數(shù)組的長度直接進行取模。

11.gc垃圾回收

什么時候觸發(fā)GC?
手動觸發(fā):當前程序去調用System.gc()的時候觸發(fā)。注意:GC回收的時候程序會停止運行,同時回收的過程中,會消耗大量的系統(tǒng)性能,所以,一般情況下我們不會主動的去調用gc回收方法。
自動觸發(fā):根據(jù)Eden區(qū)和From Space區(qū)的內存大小來決定。當內存大小不足時,則會啟動GC線程并停止應用線程
程序再申請內存的時候,系統(tǒng)(jvm)發(fā)現(xiàn)內存不足,這個時候就會觸發(fā)GC。
GC回收的算法?
標記清除
分為兩個步驟,第一個步驟就是標記,也就是標記處所有需要回收的對象,標記完成后就統(tǒng)一回收掉帶有標記的對象。這種算法優(yōu)點是簡單,缺點是效率問題,還有一個最大的缺點是空間問題,標記清除之后會產(chǎn)生大量不連續(xù)的內存碎片,當程序在以后的運行過程中需要分配較大對象時無法找到足夠的連續(xù)內存而造成內存空間浪費。
標記復制
復制將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然后再把已使用過的內存空間一次清理掉。這樣使得每次都是對其中的一塊進行內存回收,內存分配時也就不用考慮內存碎片等復雜情況。只是這種算法的代價是將內存縮小為原來的一半。
標記整理
標記整理算法與標記清除算法很相似,但最顯著的區(qū)別是:標記清除算法僅對不存活的對象進行處理,剩余存活對象不做任何處理,造成內存碎片;而標記整理算法不僅對不存活對象進行處理清除,還對剩余的存活對象進行整理,重新整理,因此其不會產(chǎn)生內存碎片。
分代收集
新生代->老年代->永久代
新生代:盡可能快速收集回收掉生命周期短的對象,一般情況下新創(chuàng)建的對象都放入到新生代中。
老年代:老年代中對象的生命周期比較長。新生代經(jīng)過N次回收以后,任然存活的對象。
永久代:主要用于存放靜態(tài)文件,如:java類,方法。
在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去,只有少量存活,那就選用復制算法。只需要付出少量存活對象的復制成本就可以完成收集。
新生代中的對象如何向老年代過度?
新生代分三個區(qū)域:eden,survivor0,survivor1三個區(qū)域,大量的對象都在eden區(qū)域,在gc的時候,先將eden區(qū)存活的對象復制到survivor0區(qū)域,然后清空了eden。當survivor0區(qū)域滿了以后,則將eden和survivor0區(qū)域中存活的對象復制到survivor1區(qū)域。然后清空eden和survivor0區(qū)域。把survivor1中的數(shù)據(jù)全部復制到survivor0區(qū)域中。經(jīng)過反復的gc,當survivor1區(qū)域不足以放下eden和survivor0區(qū)域中的存活對象,就直接將存活的對象放入到老年代。
2、老年代中因為對象存活率高、沒有額外空間對他進行分配擔保,就必須用標記-清除或者標記-整理。
注意:在jdk8的時候java廢棄了永久代,但是并不意味著我們以上的結論失效,因為java提供了與永久代類似的叫做“元空間”的技術。

12.類加載ClassLoader

類的加載包含了加載、驗證、準備、解析和初始化這 5 個階段。

13.雙親委派

類的加載器分為:
啟動類加載器(Bootstrap ClassLoader)此類加載器負責將存放在 <JAVA_HOME>\lib 目錄中的,或者被 -Xbootclasspath 參數(shù)所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如 rt.jar,名字不符合的類庫即使放在 lib 目錄中也不會被加載)類庫加載到虛擬機內存中。啟動類加載器無法被 Java 程序直接引用,用戶在編寫自定義類加載器時,如果需要把加載請求委派給啟動類加載器,直接使用 null 代替即可。
擴展類加載器(Extension ClassLoader)這個類加載器是由ExtClassLoader(sun.misc.LauncherExtClassLoader)實現(xiàn)的。 它負責將 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系統(tǒng)變量所指定路徑中的所有類庫加載到內存中,開發(fā)者可以直接使用擴展類加載器。 應用程序類加載器(Application ClassLoader)這個類加載器是由 AppClassLoader(sun.misc.LauncherAppClassLoader)實現(xiàn)的。由于這個類加載器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般稱為系統(tǒng)類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發(fā)者可以直接使用這個類加載器,如果應用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。

14.線程

線程的創(chuàng)建方式
集成thread,重寫run方法
實現(xiàn)runnable接口,重寫run方法
實現(xiàn)callable接口,重寫call方法,相對runnable,可以聲明返回類型
區(qū)別:
thread方式,最為簡單,可以通過this獲取當前線程,但是因為繼承了thread類,不能在繼承其他類了
runnable方式,子類實現(xiàn)這個接口,可以繼承其他的類,多個線程可以共享同一個target對象,沒有返回值
callable方式,子類實現(xiàn)這個接口,可以繼承其他的類,多個線程可以共享同一個target對象,有返回值

線程狀態(tài)


xc.png

wait(),yield和sleep()的區(qū)別
sleep:屬于thread類,指定休眠時間,不會釋放鎖,到時間后會自動執(zhí)行
yield:不指定時間,禮讓優(yōu)先級高的線程執(zhí)行,也不會釋放鎖,當別的線程執(zhí)行完畢后,如果沒有優(yōu)先級更高的線程需要執(zhí)行,繼續(xù)執(zhí)行當前線程,否則繼續(xù)搶占CPU資源。
Wait:屬于object類,一般不指定時間,釋放鎖,需要通過調用notify或notifyall方法喚醒,才能繼續(xù)執(zhí)行(如果給wait設置了等待時間,如果到時間還沒有喚醒,則會自動喚醒)

15.線程池

線程池的創(chuàng)建:ExecutorService service = new ThreadPoolExecutor(....)。
參數(shù)說明:corePoolSize:核心線程數(shù),默認情況下,核心線程一直存活在線程池中,即便他們在線程池中處于閑置狀態(tài)。除非我們將ThreadPoolExecutor的allowCoreThreadTimeOut屬性設為true的時候,這時候處于閑置的核心線程在等待新任務到來時會有超時策略,這個超時時間由keepAliveTime來指定。一旦超過所設置的超時時間,閑置的核心線程就會被終止
maximumPoolSize:線程池中所容納的最大線程數(shù),如果活動的線程達到這個數(shù)值以后,后續(xù)的新任務將會被阻塞。包含核心線程數(shù)+非核心線程數(shù)。
keepAliveTime:非核心線程閑置時的超時時長,對于非核心線程,閑置時間超過這個時間,非核心線程就會被回收。只有對ThreadPoolExecutor的allowCoreThreadTimeOut屬性設為true的時候,這個超時時間才會對核心線程產(chǎn)生效果
unit:時間單位
workQueue:線程池中保存等待執(zhí)行的任務的阻塞隊列
threadFactory:為線程池提供新線程的創(chuàng)建
handler:無法處理新任務的時候拋出異常
開啟線程池的兩個方法:execute,沒有返回值,不能監(jiān)聽執(zhí)行結果;submit,會返回一個future,我們可以通過get方法來回去返回值,用于監(jiān)聽線程是否執(zhí)行完畢。
關閉線程池的兩個方法:sutdown,將線程池的狀態(tài)設置為SHUTDWON狀態(tài),中斷的是閑置線程。Sutdownnow:將線程池的狀態(tài)設置為stop,中斷所有任務(包括正在執(zhí)行任務的線程和閑置線程)
線程池執(zhí)行原理:
①如果在線程池中的線程數(shù)量沒有達到核心的線程數(shù)量,這時候就回啟動一個核心線程來執(zhí)行任務。
②如果線程池中的線程數(shù)量已經(jīng)超過核心線程數(shù),這時候任務就會被插入到任務隊列中排隊等待執(zhí)行。
③由于任務隊列已滿,會立即啟動一個非核心線程來執(zhí)行任務(當然線程池里邊目前的線程數(shù)量不能超過最大線程數(shù))。
④如果線程池中的數(shù)量達到了所規(guī)定的最大值,那么就會拒絕執(zhí)行此任務,這時候就會調用RejectedExecutionHandler中的rejectedExecution方法來通知調用者。

四種線程池
1)newFixedThreadPool:所有的任務都在核心線程中執(zhí)行,且核心線程一旦創(chuàng)建,即使任務執(zhí)行完成,后期一直處于閑置狀態(tài),也不會銷毀,線程池會一直對這個線程進行維護,直到線程池關閉。如果所有的核心線程都處于活動狀態(tài),新加入的任務會被放到linkedblockingqueue這個隊列當中,且這個隊列沒有大小限制。因為核心線程創(chuàng)建后不會被銷毀,當新的任務加入時,不需要重新創(chuàng)建線程來執(zhí)行新的任務,所以相應速度非??欤且驗楹诵木€程不會銷毀,如果長時間處于閑置狀態(tài),消耗資源,所以這種線程池一般用于不會有太多任務執(zhí)行的場景下。
2)newCachedThreadPool:相當于對threadpoolexcutor的一個封裝,他的核心線程數(shù)量為0,最大線程數(shù)量是Integer.MAX_VALUE,線程池對于線程的維護時間是60秒,如果有新的任務,線程池會去內部尋找是否有閑置線程,如果有將任務分發(fā)給該線程,如果沒有,創(chuàng)建一個非核心線程去執(zhí)行,當任務執(zhí)行完成后,線程會等待60秒,如果沒有新的任務,將銷毀線程。因為最大線程數(shù)是一個非常龐大的值,且對于長時間未接受新任務的線程,會回收,所以基本不會達到最大線程的數(shù)量,所以內部傳入的隊列相當于一個空集合,不會使用到。
3)newScheduledThreadPool:是一個可定時執(zhí)行或周期執(zhí)行任務的線程池,對于非核心線程,執(zhí)行完畢后會立馬回收(scheduleWithFixedDelay當上一個任務執(zhí)行完成,然后延時時間到后開始執(zhí)行第二個任務,因為任務具體的執(zhí)行時間不能確定,所以除第一個任務外,其他任務的觸發(fā)時間不可預知;scheduleAtFixedRate當上一個任務開始執(zhí)行,延時時間到后開始執(zhí)行第二個任務,因為延時是一個固定時間,所以所有任務的觸發(fā)時間可推斷)
4)newSingleThreadPool:這個線程池當中只有一個核心線程,且最大線程也是1個,同時只能執(zhí)行一個任務,其他所有任務都放在阻塞隊列中,且這個隊列沒有大小限制(因為沒有非核心線程,所以維護時間雖然為0,如果核心線程不設置allowCoreThreadTimeOut為true,維護時間和核心線程沒有關系,所以核心線程并不會銷毀);

16.進程

系統(tǒng)進行資源分配和調度的一個獨立單位、
線程進程的區(qū)別

  1. 線程是程序執(zhí)行的最小單位,而進程是操作系統(tǒng)分配資源的最小單位;
  2. 一個進程由一個或多個線程組成,線程是一個進程中代碼的不同執(zhí)行路線
  3. 進程之間相互獨立,但同一進程下的各個線程之間共享程序的內存空間(包括代碼段,數(shù)據(jù)集,堆等)及一些進程級的資源(如打開文件和信
    號等),某進程內的線程在其他進程不可見;
  4. 調度和切換:線程上下文切換比進程上下文切換要快得多

17.網(wǎng)絡分層

wlfc.png

18.http與https協(xié)議區(qū)別

HTTP協(xié)議傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,因此使用HTTP協(xié)議傳輸隱私信息非常不安全,為了保證這些隱私數(shù)據(jù)能加密傳輸,于是網(wǎng)景公司設計了SSL(Secure Sockets Layer)協(xié)議用于對HTTP協(xié)議傳輸?shù)臄?shù)據(jù)進行加密,從而就誕生了HTTPS。簡單來說,HTTPS協(xié)議是由SSL+HTTP協(xié)議構建的可進行加密傳輸、身份認證的網(wǎng)絡協(xié)議,要比http協(xié)議安全。
1、https協(xié)議需要到ca申請證書,一般免費證書較少,因而需要一定費用。
2、http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。這個只是默認端口不一樣,實際上端口是可以改的)
4、http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構建的可進行加密傳輸、身份認證的網(wǎng)絡協(xié)議,比http協(xié)議安全。

http請求報文與響應報文格式
請求報文包含三部分:
a、請求行:包含請求方法、URI、HTTP版本信息
b、請求頭部(headers)字段
c、請求內容實體(body)
響應報文包含三部分:
a、狀態(tài)行:包含HTTP版本、狀態(tài)碼、狀態(tài)碼的原因短語
b、響應頭部(headers)字段
c、響應內容(body)實體

19.tcp與udp區(qū)別

TCP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,是專門為了在不可靠的網(wǎng)絡中提供一個可靠的端對端字節(jié)流而設計的,面向字節(jié)流。
UDP(用戶數(shù)據(jù)報協(xié)議)是iso參考模型中一種無連接的傳輸層協(xié)議,提供簡單不可靠的非連接傳輸層服務,面向報文
1) TCP是面向連接的,可靠性高;UDP是基于非連接的,可靠性低。
2) 由于TCP是連接的通信,需要有三次握手、重新確認等連接過程,會有延時,實時性差,同時過程復雜,也使其易于攻擊;UDP沒有建立連接的過程,因而實時性較強,也稍安全。
3) 在傳輸相同大小的數(shù)據(jù)時,TCP首部開銷20字節(jié);UDP首部開銷8字節(jié),TCP報頭比UDP復雜,故實際包含的用戶數(shù)據(jù)較少。TCP在IP協(xié)議的基礎上添加了序號機制、確認機制、超時重傳機制等,保證了傳輸?shù)目煽啃?,不會出現(xiàn)丟包或亂序,而UDP有丟包,故TCP開銷大,UDP開銷較小。
4) 每條TCP連接只能時點到點的;UDP支持一對一、一對多、多對一、多對多的交互通信。

Udp協(xié)議
udp: 位于傳輸層的無連接協(xié)議,也稱透明協(xié)議。如:廣播
udp:
a)提供無連接的傳輸,通信前不需要建立連接
b)提供不可靠的傳輸
c)是面向數(shù)據(jù)報的傳輸,沒有分組開銷
d)不提供擁塞控制和流量控制機制
e)數(shù)據(jù)可以不完整
場景:
流媒體服務(直播,視頻,音頻,語音電話,視頻電話)

20.三次握手

1603199881(1).png

第一次握手:建立連接時,客戶端發(fā)送syn包(syn=j)到服務器,并進入SYN_SENT狀態(tài),等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態(tài);

第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態(tài),完成三次握手。

完成三次握手,客戶端與服務器開始傳送數(shù)據(jù)

21.四次揮手

1603199979(2).png

第一步,當主機A的應用程序通知TCP數(shù)據(jù)已經(jīng)發(fā)送完畢時,TCP向主機B發(fā)送一個帶有FIN附加標記的報文段(FIN表示英文finish)。
第二步,主機B收到這個FIN報文段之后,并不立即用FIN報文段回復主機A,而是先向主機A發(fā)送一個確認序號ACK,同時通知自己相應的應用程序:對方要求關閉連接(先發(fā)送ACK的目的是為了防止在這段時間內,對方重傳FIN報文段)。
第三步,主機B的應用程序告訴TCP:我要徹底的關閉連接,TCP向主機A送一個FIN報文段。
第四步,主機A收到這個FIN報文段后,向主機B發(fā)送一個ACK表示

22.Socket

Socket:又稱”套接字”,應用程序通過”套接字”向網(wǎng)絡發(fā)送請求或應答,它是
一個針對TCP和UDP編程的接口,借助它建立TCP/UDP連接。理論上客戶端和服務器端一旦建立起連接將不會主動斷掉。依靠心跳包來維護網(wǎng)絡鏈接。

23.WebSocket

Websocket是web服務用前后端的即時通信的一種機制,使用簡單方便??梢詫崿F(xiàn)后端主動給前端發(fā)消息。
前端斷開
在使用websocket過程中,可能會出現(xiàn)網(wǎng)絡斷開的情況,比如信號不好,或者網(wǎng)絡臨時關閉,這時候websocket的連接已經(jīng)斷開,而不同瀏覽器有不同的機制,觸發(fā)onclose的時機也不同,并不會理想執(zhí)行websocket的onclose方法,我們無法知道是否斷開連接,也就無法進行重連操作。

后端斷開
如果后端因為一些情況需要斷開ws,在可控情況下,會下發(fā)一個斷連的消息通知,之后才會斷開,我們便會重連。
如果因為一些異常斷開了連接,我們是不會感應到的,所以如果我們發(fā)送了心跳一定時間之后,后端既沒有返回心跳響應消息,前端又沒有收到任何其他消息的話,我們就能斷定后端主動斷開了。

因此需要一種機制來檢測客戶端和服務端是否處于正常連接的狀態(tài)。通過在指定時間間隔發(fā)送心跳包來保證連接正常,如果連接出現(xiàn)問題,就需要手動觸發(fā)onclose事件,這時候便可進行重連操作。因此websocket心跳重連就應運而生。

24.常見的其他協(xié)議

FTP:文件傳輸協(xié)議
SMTP:郵件傳輸協(xié)議
NFS:網(wǎng)絡文件系統(tǒng)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容