TCP 三次握手和四次揮手
三次握手
- 第一次
第一次握手:建立連接時(shí)逞泄,客戶端發(fā)送syn包(syn=j)到服務(wù)器患整,并進(jìn)入SYN_SENT狀態(tài),等待服務(wù)器確認(rèn)喷众;SYN:同步序列編號(Synchronize Sequence Numbers)各谚。 - 第二次
第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶的SYN(ack=j+1)到千,同時(shí)自己也發(fā)送一個(gè)SYN包(syn=k)昌渤,即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài)憔四; - 第三次
第三次握手:客戶端收到服務(wù)器的SYN+ACK包愈涩,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)望抽,此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED(TCP連接成功)狀態(tài)履婉,完成三次握手煤篙。 - 完成三次握手,客戶端與服務(wù)器開始傳送數(shù)據(jù)毁腿,在上述過程中辑奈,還有一些重要的概念:未連接隊(duì)列。
在三次握手協(xié)議中已烤,服務(wù)器維護(hù)一個(gè)未連接隊(duì)列鸠窗,該隊(duì)列為每個(gè)客戶端的SYN包(syn=j)開設(shè)一個(gè)條目,該條目表明服務(wù)器已收到SYN包胯究,并向客戶發(fā)出確認(rèn)稍计,正在等待客戶的確認(rèn)包。這些條目所標(biāo)識的連接在服務(wù)器處于 Syn_RECV狀態(tài)裕循,當(dāng)服務(wù)器收到客戶的確認(rèn)包時(shí)臣嚣,刪除該條目,服務(wù)器進(jìn)入ESTABLISHED狀態(tài)剥哑。
四次揮手
- TCP客戶端發(fā)送一個(gè)FIN硅则,用來關(guān)閉客戶到服務(wù)器的數(shù)據(jù)傳送。
- 服務(wù)器收到這個(gè)FIN株婴,它發(fā)回一個(gè)ACK怎虫,確認(rèn)序號為收到的序號加1。和SYN一樣困介,一個(gè)FIN將占用一個(gè)序號大审。
- 服務(wù)器關(guān)閉客戶端的連接,發(fā)送一個(gè)FIN給客戶端座哩。
- 客戶端發(fā)回ACK報(bào)文確認(rèn)徒扶,并將確認(rèn)序號設(shè)置為收到序號加1。
關(guān)于為什么要三次握手和四次分手
== 和 equals 的區(qū)別是什么八回?
- == 的作用
- 對于基本類型(比如 int酷愧、flaot驾诈、double)缠诅,比較的是值是否相同。
- 對于引用類型(比如 String乍迄、Integer)管引,比較的是引用是否相同。
- equals 的作用
- 一般情況下比較的都是引用相同闯两,但是對于 String褥伴、Integer等類谅将,其重寫了 equals() 方法,使之成為了值比較重慢。
- 測試代碼 1
public class Test {
private static class Demo{
private int val;
private Demo(int v){
val = v;
}
}
public static void main(String [] args){
int i1 = 5;
int i2 = 5;
System.out.println(i1 == i2);
// int 不是引用類型的實(shí)例(對象)饥臂,所以沒有 equals
Demo d1 = new Demo(5);
Demo d2 = new Demo(5);
System.out.println(d1 == d2);
System.out.println(d1.equals(d2));
// equals() 默認(rèn)是引用比較。
String s1 = new String("666");
String s2 = new String("666");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
// 但是 String 重寫了 equals方法似踱,使之成為了值比較隅熙。
}
}
測試 1 的輸出為:
true
false
false
false
true
- 測試代碼2
public class Test {
public static void main(String [] args){
String info = "b";
String A = "abc";
String B = "a"+info+"c";
String C = "a"+"b"+"c";
// == 在引用類型下比較的是引用是否相同
System.out.println(A==B);
System.out.println(A==C);
}
}
其輸出如下:
false
true
最開始,我對這樣的結(jié)果也很訝異核芽,我預(yù)測的是兩個(gè)輸出都是 false, 因?yàn)?String 的 + 語法糖底層是通過 new StringBuffer()囚戚,然后調(diào)用 append() 和 toString() 實(shí)現(xiàn)的,明顯引用不一樣了轧简,應(yīng)該都輸出 false驰坊,但是這里還有更深層次的知識。
對象 info 和 A 均使用的字符串字面量哮独,說白話點(diǎn)拳芙,就是直接把字符串寫死,在編譯期間借嗽,這種字面量會直接放入 class 文件的常量池中态鳖,從而實(shí)現(xiàn)復(fù)用。C 雖然是動態(tài)拼接出來的字符串恶导,但是所有參與拼接的部分都是已知的字面量浆竭,在編譯期間,這種拼接會被優(yōu)化惨寿,編譯器直接幫你拼好邦泄,因此String C = "a" + "b" + "c";在class文件中被優(yōu)化成String C = "abc",A裂垦、C指向的是同一個(gè)內(nèi)存地址所以A == C成立顺囊,但是 B 的拼接過程中除了拼接字符串字面量,還有 info 這個(gè)對象的參與蕉拢,因此無法在編譯期間做優(yōu)化特碳,B 指向了和 A 不同的內(nèi)存地址。
類修飾符
修飾符 | 類別 | 含義 |
---|---|---|
public | 訪問控制符 | 將一個(gè)類聲明為公共類晕换,它可以被任何對象訪問午乓;每個(gè) Java 程序有且只有一個(gè)類是 public,它被稱為主類 闸准,其他外部類無訪問控制修飾符益愈,具有包訪問性。 |
缺省 | 訪問控制符 | 缺省修飾符時(shí),這個(gè)類只能被同一個(gè)包中的類訪問或引用蒸其;這一訪問特性又稱為包訪問性敏释。 |
abstract | 非訪問控制符 | 將一個(gè)類聲明為抽象類,沒有任何實(shí)現(xiàn)方法摸袁,需要子類提供方法的實(shí)現(xiàn)钥顽,所以不能創(chuàng)建該類的實(shí)例。 |
final | 非訪問控制符 | 將一個(gè)類聲明為非繼承類靠汁,則表示它不能被其他類繼承耳鸯。 |
上面所說的修飾符應(yīng)該是針對外部類來說的,一個(gè)類的內(nèi)部類可以被其他訪問控制修飾符 protected膀曾、default县爬、private 和非訪問控制符 static、final等修飾添谊〔圃總的來說,內(nèi)部類在修飾符上的使用上斩狱,類似于類的成員(內(nèi)部類可用的修飾符只是類成員可用的修飾符的一個(gè)真子集耳高;而且具體訪問權(quán)限還有細(xì)微的差別,因此只能說類似)所踊。
(常用)成員變量/方法修飾符
修飾符 | 類別 | 含義 |
---|---|---|
public | 訪問控制符 | 指定該變量/方法為公共的泌枪,它可以被任何對象訪問。 |
private | 訪問控制符 | 指定該變量/方法只允許自己類的方法訪問秕岛,其他任何類(包括子類)中的方法均不能訪問此變量/方法碌燕。 |
protected | 訪問控制符 | 指定該變量/方法只可以被它自己的類及其子類或同一包中的其他類訪問。在子類中可以覆蓋此變量继薛。 |
缺省 | 訪問控制符 | 表示同一包中的其他類可以訪問此成員變量/方法修壕,其它包則不能。 |
final | 非訪問控制符 | 指定該變量不能改變/該方法不能被重載 |
static | 非訪問控制符 | 指定該變量被所有實(shí)例共享/指定不需要實(shí)例化一個(gè)對象就能調(diào)用該方法 |
注意遏考,無論什么修飾符慈鸠,某類的所有成員總是對該類的方法和實(shí)例可見!
接口和抽象類的聯(lián)系與區(qū)別
聯(lián)系
接口和抽象類都不能被實(shí)例化灌具,它們都位于繼承樹的頂端青团,用于被其他類實(shí)現(xiàn)和繼承。
接口和抽象類都可以包含抽象方法咖楣,實(shí)現(xiàn)接口或繼承抽象類的普通子類都必須實(shí)現(xiàn)這些抽象方法督笆。
區(qū)別
接口里只能包含抽象方法,靜態(tài)方法和默認(rèn)方法截歉,不能為普通方法提供方法實(shí)現(xiàn)胖腾,抽象類則完全可以包含普通方法烟零。
接口里只能定義靜態(tài)常量瘪松,不能定義普通成員變量咸作,抽象類里則既可以定義普通成員變量,也可以定義靜態(tài)常量宵睦。
接口不能包含構(gòu)造器记罚,抽象類可以包含構(gòu)造器,抽象類里的構(gòu)造器并不是用于創(chuàng)建對象壳嚎,而是讓其子類調(diào)用這些構(gòu)造器來完成屬于抽象類的初始化操作桐智。
接口里不能包含初始化塊,但抽象類里完全可以包含初始化塊烟馅。
一個(gè)類最多只能有一個(gè)直接父類说庭,包括抽象類,但一個(gè)類可以直接實(shí)現(xiàn)多個(gè)接口郑趁,通過實(shí)現(xiàn)多個(gè)接口可以彌補(bǔ) Java 單繼承的不足刊驴。
String、StringBuilder寡润、StringBuffer的區(qū)別
String 創(chuàng)建的是不可變的對象捆憎,修改字符串需要 JVM 創(chuàng)建、回收 String 對象梭纹,比較耗時(shí)躲惰,適用于少量操作字符串的場景。
StringBuilder 可以在原有對象上進(jìn)行操作变抽,但卻是非線程安全的础拨,適用于單線程下頻繁操作字符串的場景。
StringBuffer 在 StringBuilder 的基礎(chǔ)上對某些方法新增了synchronized鎖原語绍载,所以是線程安全的太伊,也正是這個(gè)原因,StringBuffer 的速度要慢于 StringBuilder逛钻;適用于多線程下頻繁操作字符串的場景僚焦。